Created error table, provided error handling
This commit is contained in:
parent
22dd4222ca
commit
6a18e56cf7
|
@ -226,8 +226,8 @@
|
|||
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="DbBackups\" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -54,6 +54,8 @@ public class Controller : ControllerBase
|
|||
: Unauthorized();
|
||||
}
|
||||
|
||||
|
||||
|
||||
[HttpGet(nameof(CreateWebSocket))]
|
||||
public async Task CreateWebSocket(Token authToken)
|
||||
{
|
||||
|
@ -81,6 +83,23 @@ public class Controller : ControllerBase
|
|||
//Handle the WebSocket connection
|
||||
await WebsocketManager.HandleWebSocketConnection(webSocket);
|
||||
}
|
||||
|
||||
[HttpGet(nameof(GetAllErrorsForInstallation))]
|
||||
public ActionResult<IEnumerable<Error>> GetAllErrorsForInstallation(Int64 id, Token authToken)
|
||||
{
|
||||
var user = Db.GetSession(authToken)?.User;
|
||||
if (user == null)
|
||||
return Unauthorized();
|
||||
|
||||
var installation = Db.GetInstallationById(id);
|
||||
|
||||
if (installation is null || !user.HasAccessTo(installation))
|
||||
return Unauthorized();
|
||||
|
||||
return Db.Errors
|
||||
.Where(error => error.InstallationId == id)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
[HttpGet(nameof(GetUserById))]
|
||||
public ActionResult<User> GetUserById(Int64 id, Token authToken)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
using SQLite;
|
||||
|
||||
namespace InnovEnergy.App.Backend.DataTypes;
|
||||
|
||||
public class Error
|
||||
{
|
||||
[PrimaryKey, AutoIncrement]
|
||||
public Int64 Id { get; set; }
|
||||
public Int64 InstallationId { get; set; }
|
||||
public String ErrorDescription { get; set; } = null!;
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public String DeviceCreatedTheError { get; set; } = null!;
|
||||
public Boolean Seen { get; set; }
|
||||
}
|
|
@ -5,7 +5,6 @@ namespace InnovEnergy.App.Backend.DataTypes.Methods;
|
|||
|
||||
public static class FolderMethods
|
||||
{
|
||||
|
||||
public static IEnumerable<User> UsersWithAccess(this Folder folder)
|
||||
{
|
||||
var direct = folder.UsersWithDirectAccess();
|
||||
|
|
|
@ -141,7 +141,7 @@ public static class InstallationMethods
|
|||
foreach (var orderNumber in installation.OrderNumbers.Split(","))
|
||||
{
|
||||
var rel = relations.FirstOrDefault(i => i.OrderNumber == orderNumber);
|
||||
if ( rel != null) relations.Remove(rel);
|
||||
if ( rel != null) {relations.Remove(rel); continue;}
|
||||
var o2I = new OrderNumber2Installation
|
||||
{
|
||||
OrderNumber = orderNumber,
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace InnovEnergy.App.Backend.DataTypes;
|
|||
public abstract partial class TreeNode
|
||||
{
|
||||
[PrimaryKey, AutoIncrement]
|
||||
public virtual Int64 Id { get; set; }
|
||||
public Int64 Id { get; set; }
|
||||
public virtual String Name { get; set; } = ""; // overridden by User (unique)
|
||||
public String Information { get; set; } = ""; // unstructured random info
|
||||
|
||||
|
|
|
@ -20,6 +20,11 @@ public static partial class Db
|
|||
return Insert(installation);
|
||||
}
|
||||
|
||||
public static Boolean Create(Error error)
|
||||
{
|
||||
return Insert(error);
|
||||
}
|
||||
|
||||
public static Boolean Create(Folder folder)
|
||||
{
|
||||
return Insert(folder);
|
||||
|
@ -49,4 +54,30 @@ public static partial class Db
|
|||
{
|
||||
return Insert(o2i);
|
||||
}
|
||||
|
||||
public static void HandleError(Error newError,int installationId)
|
||||
{
|
||||
//Find the total number of errors for this installation
|
||||
var totalErrors = Errors.Count(error => error.InstallationId == installationId);
|
||||
|
||||
//If there are 100 errors, remove the one with the oldest timestamp
|
||||
if (totalErrors == 100)
|
||||
{
|
||||
var oldestError =
|
||||
Errors.Where(error => error.InstallationId == installationId)
|
||||
.OrderBy(error => error.CreatedAt)
|
||||
.FirstOrDefault();
|
||||
|
||||
//Remove the old error
|
||||
Delete(oldestError);
|
||||
|
||||
//Add the new error
|
||||
Create(newError);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("---------------Added the new Error to the database-----------------");
|
||||
Create(newError);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,21 +15,36 @@ namespace InnovEnergy.App.Backend.Database;
|
|||
|
||||
public static partial class Db
|
||||
{
|
||||
// internal const String DbPath = "./db.sqlite";
|
||||
private static SQLiteConnection Connection { get; } = InitConnection();
|
||||
|
||||
private static SQLiteConnection Connection { get; } = ((Func<SQLiteConnection>)(() =>
|
||||
private static SQLiteConnection InitConnection()
|
||||
{
|
||||
var latestDb = new DirectoryInfo(@"DbBackups").GetFiles()
|
||||
.OrderBy(f => f.LastWriteTime)
|
||||
.Last().Name;
|
||||
var latestDb = new DirectoryInfo("DbBackups")
|
||||
.GetFiles()
|
||||
.OrderBy(f => f.LastWriteTime)
|
||||
.Last().Name;
|
||||
|
||||
var fileConnection = new SQLiteConnection("DbBackups/"+latestDb);
|
||||
//This is the file connection from the DbBackups folder
|
||||
var fileConnection = new SQLiteConnection("DbBackups/" + latestDb);
|
||||
|
||||
//Create a table if it does not exist
|
||||
fileConnection.CreateTable<User>();
|
||||
fileConnection.CreateTable<Installation>();
|
||||
fileConnection.CreateTable<Folder>();
|
||||
fileConnection.CreateTable<FolderAccess>();
|
||||
fileConnection.CreateTable<InstallationAccess>();
|
||||
fileConnection.CreateTable<Session>();
|
||||
fileConnection.CreateTable<OrderNumber2Installation>();
|
||||
fileConnection.CreateTable<Error>();
|
||||
|
||||
return CopyDbToMemory(fileConnection);
|
||||
}
|
||||
|
||||
Console.Out.Write(latestDb);
|
||||
private static SQLiteConnection CopyDbToMemory(SQLiteConnection fileConnection)
|
||||
{
|
||||
var memoryConnection = new SQLiteConnection(":memory:");
|
||||
|
||||
// fileConnection.Backup(memoryConnection.DatabasePath);
|
||||
|
||||
//Create a table if it does not exist in main memory
|
||||
memoryConnection.CreateTable<User>();
|
||||
memoryConnection.CreateTable<Installation>();
|
||||
memoryConnection.CreateTable<Folder>();
|
||||
|
@ -37,18 +52,21 @@ public static partial class Db
|
|||
memoryConnection.CreateTable<InstallationAccess>();
|
||||
memoryConnection.CreateTable<Session>();
|
||||
memoryConnection.CreateTable<OrderNumber2Installation>();
|
||||
|
||||
fileConnection.Table<Session> ().ForEach(memoryConnection.Insert);
|
||||
fileConnection.Table<Folder> ().ForEach(memoryConnection.Insert);
|
||||
fileConnection.Table<Installation> ().ForEach(memoryConnection.Insert);
|
||||
fileConnection.Table<User> ().ForEach(memoryConnection.Insert);
|
||||
fileConnection.Table<FolderAccess> ().ForEach(memoryConnection.Insert);
|
||||
fileConnection.Table<InstallationAccess> ().ForEach(memoryConnection.Insert);
|
||||
fileConnection.Table<OrderNumber2Installation>().ForEach(memoryConnection.Insert);
|
||||
memoryConnection.CreateTable<Error>();
|
||||
|
||||
//Copy all the existing tables from the disk to main memory
|
||||
fileConnection.Table<Session>().ForEach(memoryConnection.Insert);
|
||||
fileConnection.Table<Folder>().ForEach(memoryConnection.Insert);
|
||||
fileConnection.Table<Installation>().ForEach(memoryConnection.Insert);
|
||||
fileConnection.Table<User>().ForEach(memoryConnection.Insert);
|
||||
fileConnection.Table<FolderAccess>().ForEach(memoryConnection.Insert);
|
||||
fileConnection.Table<InstallationAccess>().ForEach(memoryConnection.Insert);
|
||||
fileConnection.Table<OrderNumber2Installation>().ForEach(memoryConnection.Insert);
|
||||
fileConnection.Table<Error>().ForEach(memoryConnection.Insert);
|
||||
|
||||
return memoryConnection;
|
||||
}))();
|
||||
|
||||
}
|
||||
|
||||
public static void BackupDatabase()
|
||||
{
|
||||
var filename = "db-" + DateTimeOffset.UtcNow.ToUnixTimeSeconds() + ".sqlite";
|
||||
|
@ -62,17 +80,16 @@ public static partial class Db
|
|||
public static TableQuery<FolderAccess> FolderAccess => Connection.Table<FolderAccess>();
|
||||
public static TableQuery<InstallationAccess> InstallationAccess => Connection.Table<InstallationAccess>();
|
||||
public static TableQuery<OrderNumber2Installation> OrderNumber2Installation => Connection.Table<OrderNumber2Installation>();
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
public static TableQuery<Error> Errors => Connection.Table<Error>();
|
||||
|
||||
public static void Init(){
|
||||
// used to force static constructor
|
||||
//Since this class is static, we call Init method from the Program.cs to initialize all the fields of the class
|
||||
}
|
||||
|
||||
|
||||
//This is the constructor of the class
|
||||
static Db()
|
||||
{
|
||||
// on startup create/migrate tables
|
||||
|
||||
Connection.RunInTransaction(() =>
|
||||
{
|
||||
Connection.CreateTable<User>();
|
||||
|
@ -82,6 +99,7 @@ public static partial class Db
|
|||
Connection.CreateTable<InstallationAccess>();
|
||||
Connection.CreateTable<Session>();
|
||||
Connection.CreateTable<OrderNumber2Installation>();
|
||||
Connection.CreateTable<Error>();
|
||||
});
|
||||
|
||||
Observable.Interval(TimeSpan.FromHours(0.5))
|
||||
|
|
|
@ -34,6 +34,20 @@ public static partial class Db
|
|||
return delete>0;
|
||||
}
|
||||
}
|
||||
|
||||
public static Boolean Delete(Error errorToDelete)
|
||||
{
|
||||
var deleteSuccess = RunTransaction(DeleteError);
|
||||
if (deleteSuccess)
|
||||
BackupDatabase();
|
||||
return deleteSuccess;
|
||||
|
||||
|
||||
Boolean DeleteError()
|
||||
{
|
||||
return Errors.Delete(error => error.Id == errorToDelete.Id) >0;
|
||||
}
|
||||
}
|
||||
|
||||
public static Boolean Delete(Installation installation)
|
||||
{
|
||||
|
|
|
@ -33,7 +33,4 @@ public static partial class Db
|
|||
|
||||
return Update(obj: user);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,6 +1,9 @@
|
|||
|
||||
public class StatusMessage
|
||||
{
|
||||
public required int InstallationId { get; init; }
|
||||
public required int Status { get; init; }
|
||||
public required int InstallationId { get; init; }
|
||||
public required int Status { get; init; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public String Error { get; init; } = null!;
|
||||
public String DeviceCreatedTheError { get; init; } = null!;
|
||||
}
|
|
@ -5,6 +5,7 @@ using System.Net.WebSockets;
|
|||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using InnovEnergy.App.Backend.Database;
|
||||
using InnovEnergy.App.Backend.DataTypes;
|
||||
using RabbitMQ.Client;
|
||||
using RabbitMQ.Client.Events;
|
||||
|
||||
|
@ -19,7 +20,6 @@ public static class WebsocketManager
|
|||
|
||||
public static void InformInstallationsToSubscribeToRabbitMq()
|
||||
{
|
||||
//var installationIps = new List<string> { "10.2.3.115" };
|
||||
var installationIps = Db.Installations.Select(inst => inst.VpnIp).ToList();
|
||||
Console.WriteLine("Count is "+installationIps.Count);
|
||||
var maxRetransmissions = 2;
|
||||
|
@ -83,13 +83,31 @@ public static class WebsocketManager
|
|||
|
||||
lock (InstallationConnections)
|
||||
{
|
||||
// Process the received message
|
||||
//Consumer received a 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;
|
||||
|
||||
//This is an error message
|
||||
if (receivedStatusMessage.Status==2)
|
||||
{
|
||||
Console.WriteLine("-----------------------New error-----------------------");
|
||||
|
||||
Error newError = new Error
|
||||
{
|
||||
InstallationId = receivedStatusMessage.InstallationId,
|
||||
ErrorDescription = receivedStatusMessage.Error,
|
||||
CreatedAt = receivedStatusMessage.CreatedAt,
|
||||
DeviceCreatedTheError = receivedStatusMessage.DeviceCreatedTheError,
|
||||
Seen = false
|
||||
};
|
||||
//Create a new error and add it to the database
|
||||
Db.HandleError(newError,receivedStatusMessage.InstallationId);
|
||||
|
||||
}
|
||||
|
||||
if (!InstallationConnections.ContainsKey(installationId))
|
||||
{
|
||||
|
|
|
@ -3,6 +3,10 @@ namespace InnovEnergy.App.SaliMax.MiddlewareClasses;
|
|||
|
||||
public class StatusMessage
|
||||
{
|
||||
public required int InstallationId { get; init; }
|
||||
public required int Status { get; init; }
|
||||
|
||||
public required int InstallationId { get; init; }
|
||||
public required int Status { get; init; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public String Error { get; set; } = null!;
|
||||
public String DeviceCreatedTheError { get; set; } = null!;
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Net.Sockets;
|
||||
|
@ -265,10 +266,14 @@ internal static class Program
|
|||
{
|
||||
_subscribeToQueueForTheFirstTime = true;
|
||||
SubscribeToQueue(currentSalimaxState, s3Bucket);
|
||||
|
||||
if (_subscribedToQueue && currentSalimaxState != _prevSalimaxState)
|
||||
{
|
||||
_prevSalimaxState = currentSalimaxState;
|
||||
}
|
||||
}
|
||||
|
||||
//If already subscribed to the queue and the status has been changed, update the queue
|
||||
if (_subscribedToQueue && currentSalimaxState != _prevSalimaxState)
|
||||
else if (_subscribedToQueue && currentSalimaxState != _prevSalimaxState)
|
||||
{
|
||||
_prevSalimaxState = currentSalimaxState;
|
||||
if (s3Bucket != null)
|
||||
|
@ -343,12 +348,18 @@ internal static class Program
|
|||
private static void InformMiddleware(String? bucket, int status)
|
||||
{
|
||||
int.TryParse(bucket[0].ToString(), out var installationId);
|
||||
|
||||
var jsonObject = new StatusMessage
|
||||
{
|
||||
InstallationId = installationId,
|
||||
Status = status
|
||||
Status = status,
|
||||
};
|
||||
|
||||
if (status == 2)
|
||||
{
|
||||
jsonObject.CreatedAt = DateTime.Now;
|
||||
jsonObject.Error = "Battery Temperature High";
|
||||
jsonObject.DeviceCreatedTheError = "Battery/1";
|
||||
}
|
||||
|
||||
var message = JsonSerializer.Serialize(jsonObject);
|
||||
var body = Encoding.UTF8.GetBytes(message);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System.ComponentModel;
|
||||
using InnovEnergy.Lib.Devices.Trumpf.SystemControl;
|
||||
using InnovEnergy.Lib.Devices.Trumpf.TruConvertAc.DataTypes;
|
||||
using InnovEnergy.Lib.Units.Composite;
|
||||
|
@ -18,6 +19,9 @@ public class AcDcDevicesRecord
|
|||
public SystemControlRegisters? SystemControl { get; }
|
||||
public IReadOnlyList<AcDcRecord> Devices { get; init; }
|
||||
|
||||
//public IEnumerable<AlarmMessage> Alarms => new []{AlarmMessage.BatteryOvervoltage}; //Devices.SelectMany(d => d.Status.Alarms).Distinct();
|
||||
//public IEnumerable<WarningMessage> Warnings => new []{WarningMessage.TempDerating}; //Devices.SelectMany(d => d.Status.Warnings).Distinct();
|
||||
|
||||
public IEnumerable<AlarmMessage> Alarms => Devices.SelectMany(d => d.Status.Alarms).Distinct();
|
||||
public IEnumerable<WarningMessage> Warnings => Devices.SelectMany(d => d.Status.Warnings).Distinct();
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ public enum WarningMessage : UInt16
|
|||
{
|
||||
NoWarning = 00000,
|
||||
|
||||
/*
|
||||
|
||||
|
||||
// these warnings are not official (not in the manual), and they seem to collide with the DCDC warnings
|
||||
// so I commented them
|
||||
|
@ -28,5 +28,5 @@ public enum WarningMessage : UInt16
|
|||
RuntimeEeprom = 11023, //AC-DC module warning
|
||||
Overcurrent = 11024 //Overcurrent handling is active
|
||||
|
||||
*/
|
||||
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
import axios from 'axios';
|
||||
|
||||
export const axiosConfigWithoutToken = axios.create({
|
||||
baseURL: 'https://monitor.innov.energy/api'
|
||||
// baseURL: 'http://127.0.0.1:7087/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: 'http://127.0.0.1:7087/api'
|
||||
//baseURL: 'https://monitor.innov.energy/api'
|
||||
baseURL: 'http://127.0.0.1:7087/api'
|
||||
});
|
||||
|
||||
axiosConfig.defaults.params = {};
|
||||
|
|
|
@ -28,7 +28,6 @@ import {
|
|||
extractValues,
|
||||
TopologyValues
|
||||
} from 'src/content/dashboards/Log/graph.util';
|
||||
import { Notification } from 'src/interfaces/S3Types';
|
||||
import { WebSocketContext } from 'src/contexts/WebSocketContextProvider';
|
||||
import Topology from '../Topology/Topology';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
@ -62,8 +61,6 @@ function Installation(props: singleInstallationProps) {
|
|||
deleteInstallation
|
||||
} = installationContext;
|
||||
|
||||
const [warnings, setWarnings] = useState<Notification[]>([]);
|
||||
const [errors, setErrors] = useState<Notification[]>([]);
|
||||
const [errorLoadingS3Data, setErrorLoadingS3Data] = useState(false);
|
||||
const webSocketsContext = useContext(WebSocketContext);
|
||||
const { getStatus } = webSocketsContext;
|
||||
|
@ -153,9 +150,6 @@ function Installation(props: singleInstallationProps) {
|
|||
return;
|
||||
}
|
||||
|
||||
const newWarnings: Notification[] = [];
|
||||
const newErrors: Notification[] = [];
|
||||
|
||||
if (
|
||||
res === FetchResult.notAvailable ||
|
||||
res === FetchResult.tryLater
|
||||
|
@ -681,9 +675,8 @@ function Installation(props: singleInstallationProps) {
|
|||
{currentTab === 'live' && <Topology values={values}></Topology>}
|
||||
{currentTab === 'log' && (
|
||||
<Log
|
||||
warnings={warnings}
|
||||
errors={errors}
|
||||
errorLoadingS3Data={errorLoadingS3Data}
|
||||
id={props.current_installation.id}
|
||||
></Log>
|
||||
)}
|
||||
</Grid>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import {
|
||||
Alert,
|
||||
Card,
|
||||
|
@ -14,26 +14,49 @@ import {
|
|||
TableRow,
|
||||
useTheme
|
||||
} from '@mui/material';
|
||||
import WarningIcon from '@mui/icons-material/Warning';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { Notification } from 'src/interfaces/S3Types';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import ErrorIcon from '@mui/icons-material/Error';
|
||||
import axiosConfig from '../../../Resources/axiosConfig';
|
||||
import { AxiosError, AxiosResponse } from 'axios/index';
|
||||
import routes from '../../../Resources/routes.json';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { TokenContext } from '../../../contexts/tokenContext';
|
||||
import { ErrorMessage } from '../../../interfaces/S3Types';
|
||||
|
||||
interface LogProps {
|
||||
warnings: Notification[];
|
||||
errors: Notification[];
|
||||
errorLoadingS3Data: boolean;
|
||||
id: number;
|
||||
}
|
||||
|
||||
function Log(props: LogProps) {
|
||||
const theme = useTheme();
|
||||
//const [warnings, setWarnings] = useState<Notification[]>([]);
|
||||
const [errors, setErrors] = useState<ErrorMessage[]>([]);
|
||||
const navigate = useNavigate();
|
||||
const tokencontext = useContext(TokenContext);
|
||||
const { removeToken } = tokencontext;
|
||||
|
||||
useEffect(() => {
|
||||
axiosConfig
|
||||
.get(`/GetAllErrorsForInstallation?id=${props.id}`)
|
||||
.then((res: AxiosResponse<ErrorMessage[]>) => {
|
||||
setErrors(res.data);
|
||||
})
|
||||
.catch((err: AxiosError) => {
|
||||
if (err.response && err.response.status == 401) {
|
||||
removeToken();
|
||||
navigate(routes.login);
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Container maxWidth="xl">
|
||||
<Grid container>
|
||||
<Grid item xs={12} md={12}>
|
||||
{(props.errors.length > 0 || props.warnings.length > 0) && (
|
||||
{/* IT SHOULD BE {(errors.length > 0 || props.warnings.length > 0) && (*/}
|
||||
{errors.length > 0 && (
|
||||
<Card sx={{ marginTop: '10px' }}>
|
||||
<Divider />
|
||||
<TableContainer>
|
||||
|
@ -43,25 +66,26 @@ function Log(props: LogProps) {
|
|||
<TableCell>
|
||||
<FormattedMessage id="type" defaultMessage="Type" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<FormattedMessage id="device" defaultMessage="Device" />
|
||||
</TableCell>
|
||||
|
||||
<TableCell>
|
||||
<FormattedMessage
|
||||
id="description"
|
||||
defaultMessage="Description"
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<FormattedMessage id="device" defaultMessage="Device" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<FormattedMessage id="date" defaultMessage="Date" />
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<FormattedMessage id="time" defaultMessage="Time" />
|
||||
<FormattedMessage id="seen" defaultMessage="Seen" />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{props.errors.map((error, index) => {
|
||||
{errors.map((error, index) => {
|
||||
return (
|
||||
<TableRow hover key={index}>
|
||||
<TableCell>
|
||||
|
@ -82,9 +106,9 @@ function Log(props: LogProps) {
|
|||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '5px' }}
|
||||
sx={{ marginTop: '5px', marginLeft: '-40px' }}
|
||||
>
|
||||
{error.device}
|
||||
{error.errorDescription}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
|
@ -96,7 +120,7 @@ function Log(props: LogProps) {
|
|||
noWrap
|
||||
sx={{ marginTop: '5px' }}
|
||||
>
|
||||
{error.description}
|
||||
{error.deviceCreatedTheError}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
|
@ -106,9 +130,9 @@ function Log(props: LogProps) {
|
|||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '5px' }}
|
||||
sx={{ marginTop: '5px', marginLeft: '-40px' }}
|
||||
>
|
||||
{error.date}
|
||||
{error.createdAt}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
|
@ -118,87 +142,87 @@ function Log(props: LogProps) {
|
|||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '5px' }}
|
||||
sx={{ marginTop: '5px', marginLeft: '10px' }}
|
||||
>
|
||||
{error.time}
|
||||
{error.seen == false ? 'No' : 'Yes'}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
|
||||
{props.warnings.map((warning, index) => {
|
||||
return (
|
||||
<TableRow hover key={index}>
|
||||
<TableCell>
|
||||
<WarningIcon
|
||||
sx={{
|
||||
color: '#ffc04d',
|
||||
width: 25,
|
||||
height: 25,
|
||||
marginLeft: '5px',
|
||||
marginTop: '8px'
|
||||
}}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '10px' }}
|
||||
>
|
||||
{warning.device}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '10px' }}
|
||||
>
|
||||
{warning.description}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '10px' }}
|
||||
>
|
||||
{warning.date}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Typography
|
||||
variant="body1"
|
||||
fontWeight="bold"
|
||||
color="text.primary"
|
||||
gutterBottom
|
||||
noWrap
|
||||
sx={{ marginTop: '10px' }}
|
||||
>
|
||||
{warning.time}
|
||||
</Typography>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
{/*{props.warnings.map((warning, index) => {*/}
|
||||
{/* return (*/}
|
||||
{/* <TableRow hover key={index}>*/}
|
||||
{/* <TableCell>*/}
|
||||
{/* <WarningIcon*/}
|
||||
{/* sx={{*/}
|
||||
{/* color: '#ffc04d',*/}
|
||||
{/* width: 25,*/}
|
||||
{/* height: 25,*/}
|
||||
{/* marginLeft: '5px',*/}
|
||||
{/* marginTop: '8px'*/}
|
||||
{/* }}*/}
|
||||
{/* />*/}
|
||||
{/* </TableCell>*/}
|
||||
{/* <TableCell>*/}
|
||||
{/* <Typography*/}
|
||||
{/* variant="body1"*/}
|
||||
{/* fontWeight="bold"*/}
|
||||
{/* color="text.primary"*/}
|
||||
{/* gutterBottom*/}
|
||||
{/* noWrap*/}
|
||||
{/* sx={{ marginTop: '10px' }}*/}
|
||||
{/* >*/}
|
||||
{/* {warning.device}*/}
|
||||
{/* </Typography>*/}
|
||||
{/* </TableCell>*/}
|
||||
{/* <TableCell>*/}
|
||||
{/* <Typography*/}
|
||||
{/* variant="body1"*/}
|
||||
{/* fontWeight="bold"*/}
|
||||
{/* color="text.primary"*/}
|
||||
{/* gutterBottom*/}
|
||||
{/* noWrap*/}
|
||||
{/* sx={{ marginTop: '10px' }}*/}
|
||||
{/* >*/}
|
||||
{/* {warning.description}*/}
|
||||
{/* </Typography>*/}
|
||||
{/* </TableCell>*/}
|
||||
{/* <TableCell>*/}
|
||||
{/* <Typography*/}
|
||||
{/* variant="body1"*/}
|
||||
{/* fontWeight="bold"*/}
|
||||
{/* color="text.primary"*/}
|
||||
{/* gutterBottom*/}
|
||||
{/* noWrap*/}
|
||||
{/* sx={{ marginTop: '10px' }}*/}
|
||||
{/* >*/}
|
||||
{/* {warning.date}*/}
|
||||
{/* </Typography>*/}
|
||||
{/* </TableCell>*/}
|
||||
{/* <TableCell>*/}
|
||||
{/* <Typography*/}
|
||||
{/* variant="body1"*/}
|
||||
{/* fontWeight="bold"*/}
|
||||
{/* color="text.primary"*/}
|
||||
{/* gutterBottom*/}
|
||||
{/* noWrap*/}
|
||||
{/* sx={{ marginTop: '10px' }}*/}
|
||||
{/* >*/}
|
||||
{/* {warning.time}*/}
|
||||
{/* </Typography>*/}
|
||||
{/* </TableCell>*/}
|
||||
{/* </TableRow>*/}
|
||||
{/* );*/}
|
||||
{/*})}*/}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{!props.errorLoadingS3Data && props.errors.length == 0 && (
|
||||
{!props.errorLoadingS3Data && errors.length == 0 && (
|
||||
<Alert
|
||||
severity="error"
|
||||
sx={{
|
||||
|
@ -242,27 +266,27 @@ function Log(props: LogProps) {
|
|||
</Alert>
|
||||
)}
|
||||
|
||||
{!props.errorLoadingS3Data && props.warnings.length == 0 && (
|
||||
<Alert
|
||||
severity="error"
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
//marginBottom: '20px'
|
||||
marginTop: '20px'
|
||||
}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="nowarnings"
|
||||
defaultMessage="There are no warnings"
|
||||
/>
|
||||
<IconButton
|
||||
color="inherit"
|
||||
size="small"
|
||||
sx={{ marginLeft: '4px' }}
|
||||
></IconButton>
|
||||
</Alert>
|
||||
)}
|
||||
{/*{!props.errorLoadingS3Data && props.warnings.length == 0 && (*/}
|
||||
{/* <Alert*/}
|
||||
{/* severity="error"*/}
|
||||
{/* sx={{*/}
|
||||
{/* display: 'flex',*/}
|
||||
{/* alignItems: 'center',*/}
|
||||
{/* //marginBottom: '20px'*/}
|
||||
{/* marginTop: '20px'*/}
|
||||
{/* }}*/}
|
||||
{/* >*/}
|
||||
{/* <FormattedMessage*/}
|
||||
{/* id="nowarnings"*/}
|
||||
{/* defaultMessage="There are no warnings"*/}
|
||||
{/* />*/}
|
||||
{/* <IconButton*/}
|
||||
{/* color="inherit"*/}
|
||||
{/* size="small"*/}
|
||||
{/* sx={{ marginLeft: '4px' }}*/}
|
||||
{/* ></IconButton>*/}
|
||||
{/* </Alert>*/}
|
||||
{/*)}*/}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Container>
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
import { UnixTime } from '../../../dataCache/time';
|
||||
import { I_S3Credentials } from '../../../interfaces/S3Types';
|
||||
import { FetchResult } from '../../../dataCache/dataCache';
|
||||
import { DataRecord } from '../../../dataCache/data';
|
||||
import { S3Access } from '../../../dataCache/S3/S3Access';
|
||||
import { parseCsv } from './graph.util';
|
||||
|
||||
export const fetchData = (
|
||||
timestamp: UnixTime,
|
||||
s3Credentials?: I_S3Credentials
|
||||
): Promise<FetchResult<DataRecord>> => {
|
||||
const s3Path = `${timestamp.ticks}.csv`;
|
||||
if (s3Credentials && s3Credentials.s3Bucket) {
|
||||
const s3Access = new S3Access(
|
||||
s3Credentials.s3Bucket,
|
||||
s3Credentials.s3Region,
|
||||
s3Credentials.s3Provider,
|
||||
s3Credentials.s3Key,
|
||||
s3Credentials.s3Secret
|
||||
);
|
||||
return s3Access
|
||||
.get(s3Path)
|
||||
.then(async (r) => {
|
||||
if (r.status === 404) {
|
||||
return Promise.resolve(FetchResult.notAvailable);
|
||||
} else if (r.status === 200) {
|
||||
const text = await r.text();
|
||||
return parseCsv(text);
|
||||
} else {
|
||||
return Promise.resolve(FetchResult.notAvailable);
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
return Promise.resolve(FetchResult.tryLater);
|
||||
});
|
||||
}
|
||||
};
|
|
@ -6,9 +6,10 @@ export interface I_S3Credentials {
|
|||
s3Bucket?: string;
|
||||
}
|
||||
|
||||
export interface Notification {
|
||||
device: string;
|
||||
description: string;
|
||||
date: string;
|
||||
time: string;
|
||||
export interface ErrorMessage {
|
||||
installationId: number;
|
||||
createdAt: Date;
|
||||
errorDescription: string;
|
||||
deviceCreatedTheError: string;
|
||||
seen: boolean;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue