Update dbus-fzsonic skripts
|
@ -4,6 +4,9 @@ namespace InnovEnergy.App.Backend.DataTypes;
|
||||||
|
|
||||||
public class Installation : TreeNode
|
public class Installation : TreeNode
|
||||||
{
|
{
|
||||||
|
//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 Location { get; set; } = "";
|
public String Location { get; set; } = "";
|
||||||
public String Region { get; set; } = "";
|
public String Region { get; set; } = "";
|
||||||
public String Country { get; set; } = "";
|
public String Country { get; set; } = "";
|
||||||
|
@ -20,9 +23,10 @@ public class Installation : TreeNode
|
||||||
public String ReadRoleId { get; set; } = "";
|
public String ReadRoleId { get; set; } = "";
|
||||||
public String WriteRoleId { get; set; } = "";
|
public String WriteRoleId { get; set; } = "";
|
||||||
public Boolean TestingMode { get; set; } = false;
|
public Boolean TestingMode { get; set; } = false;
|
||||||
|
public int Status { get; set; } = -1;
|
||||||
public int Product { get; set; } = 0;
|
public int Product { get; set; } = 0;
|
||||||
public int Device { get; set; } = 0;
|
public int Device { get; set; } = 0;
|
||||||
|
|
||||||
[Ignore]
|
[Ignore]
|
||||||
public String OrderNumbers { get; set; }
|
public String OrderNumbers { get; set; }
|
||||||
public String VrmLink { get; set; } = "";
|
public String VrmLink { get; set; } = "";
|
||||||
|
|
|
@ -282,9 +282,9 @@ public static class SessionMethods
|
||||||
&& Db.Delete(installation)
|
&& Db.Delete(installation)
|
||||||
&& await installation.RevokeReadKey()
|
&& await installation.RevokeReadKey()
|
||||||
&& await installation.RevokeWriteKey()
|
&& await installation.RevokeWriteKey()
|
||||||
&& await installation.DeleteBucket()
|
|
||||||
&& await installation.RemoveReadRole()
|
&& await installation.RemoveReadRole()
|
||||||
&& await installation.RemoveWriteRole();
|
&& await installation.RemoveWriteRole()
|
||||||
|
&& await installation.DeleteBucket();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,28 +7,19 @@ namespace InnovEnergy.App.Backend.Database;
|
||||||
|
|
||||||
public static partial class Db
|
public static partial class Db
|
||||||
{
|
{
|
||||||
private static int _backupCounter = 0;
|
|
||||||
private static Boolean Insert(Object obj)
|
private static Boolean Insert(Object obj)
|
||||||
{
|
{
|
||||||
var success = Connection.Insert(obj) > 0;
|
var success = Connection.Insert(obj) > 0;
|
||||||
if (success)
|
if (success) Backup();
|
||||||
{
|
|
||||||
_backupCounter++;
|
|
||||||
if (_backupCounter > 100)
|
|
||||||
{
|
|
||||||
_backupCounter = 0;
|
|
||||||
BackupDatabase();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Boolean Create(Installation installation)
|
public static Boolean Create(Installation installation)
|
||||||
{
|
{
|
||||||
installation.S3BucketId = Installations.Where(inst => inst.Product == installation.Product).Max(inst => (int?)inst.S3BucketId)+1 ?? 0;
|
// The bucket Id it calculated as follows: It is 1 + the maximum bucket id of all the existing installations of the same product
|
||||||
|
|
||||||
// SQLite wrapper is smart and *modifies* t's Id to the one generated (autoincrement) by the insertion
|
// SQLite wrapper is smart and *modifies* t's Id to the one generated (autoincrement) by the insertion
|
||||||
|
installation.S3BucketId = Installations.Where(inst => inst.Product == installation.Product).Max(inst => (int?)inst.S3BucketId)+1 ?? 0;
|
||||||
return Insert(installation);
|
return Insert(installation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,21 +94,8 @@ public static partial class Db
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void UpdateAction(UserAction updatedAction)
|
//This function is called from the RabbitMQ manager when a new error arrives to the database.
|
||||||
{
|
//We keep only the last 100 errors for each installation. If we already have stored 100 errors, we delete the older one and we insert the new one.
|
||||||
var existingAction = UserActions.FirstOrDefault(action => action.Id == updatedAction.Id);
|
|
||||||
|
|
||||||
|
|
||||||
if (existingAction != null)
|
|
||||||
{
|
|
||||||
//existingAction.Description = updatedAction.Description;
|
|
||||||
//existingAction.Timestamp = updatedAction.Timestamp;
|
|
||||||
//existingAction.TestingMode = updatedAction.TestingMode;
|
|
||||||
Update(updatedAction);
|
|
||||||
Console.WriteLine("---------------Updated the Action in the database-----------------");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static void HandleError(Error newError,int installationId)
|
public static void HandleError(Error newError,int installationId)
|
||||||
{
|
{
|
||||||
|
@ -140,7 +118,7 @@ public static partial class Db
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLine("---------------Added the new Error to the database-----------------");
|
Console.WriteLine("---------------Added the new Alarm to the database-----------------");
|
||||||
Create(newError);
|
Create(newError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,10 +136,10 @@ public static partial class Db
|
||||||
.OrderBy(warning => warning.Date)
|
.OrderBy(warning => warning.Date)
|
||||||
.FirstOrDefault();
|
.FirstOrDefault();
|
||||||
|
|
||||||
//Remove the old error
|
//Remove the old warning
|
||||||
Delete(oldestWarning);
|
Delete(oldestWarning);
|
||||||
|
|
||||||
//Add the new error
|
//Add the new warning
|
||||||
Create(newWarning);
|
Create(newWarning);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -9,6 +9,9 @@ using SQLiteConnection = SQLite.SQLiteConnection;
|
||||||
|
|
||||||
namespace InnovEnergy.App.Backend.Database;
|
namespace InnovEnergy.App.Backend.Database;
|
||||||
|
|
||||||
|
//The methods of the Db class are located in multiple files (Create.cs, Read,cs, Delete.cs, Update.cs)
|
||||||
|
//That's why the class definition is partial
|
||||||
|
|
||||||
public static partial class Db
|
public static partial class Db
|
||||||
{
|
{
|
||||||
private static SQLiteConnection Connection { get; } = InitConnection();
|
private static SQLiteConnection Connection { get; } = InitConnection();
|
||||||
|
@ -30,7 +33,7 @@ public static partial class Db
|
||||||
//Since this class is static, we call Init method from the Program.cs to initialize all the fields of the class
|
//Since this class is static, we call Init method from the Program.cs to initialize all the fields of the class
|
||||||
//When a class is loaded, the fields are initialized before the constructor's code is executed.
|
//When a class is loaded, the fields are initialized before the constructor's code is executed.
|
||||||
//The TableQuery fields are lazy meaning that they will be initialized when they get accessed
|
//The TableQuery fields are lazy meaning that they will be initialized when they get accessed
|
||||||
//The connection searches for the latest backup and it binds all the tables to it.
|
//The connection searches for the latest backup and binds all the tables to it.
|
||||||
}
|
}
|
||||||
|
|
||||||
//This is the constructor of the class
|
//This is the constructor of the class
|
||||||
|
@ -90,7 +93,7 @@ public static partial class Db
|
||||||
Connection.Backup("DbBackups/" + filename);
|
Connection.Backup("DbBackups/" + filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Delete all by 10 snapshots every 24 hours.
|
//Delete all except 10 snapshots every 24 hours.
|
||||||
private static async Task DeleteSnapshots()
|
private static async Task DeleteSnapshots()
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
|
|
|
@ -1,16 +1,12 @@
|
||||||
using InnovEnergy.App.Backend.DataTypes;
|
using InnovEnergy.App.Backend.DataTypes;
|
||||||
using InnovEnergy.App.Backend.DataTypes.Methods;
|
using InnovEnergy.App.Backend.DataTypes.Methods;
|
||||||
using InnovEnergy.App.Backend.Relations;
|
using InnovEnergy.App.Backend.Relations;
|
||||||
using Microsoft.AspNetCore.Authentication.OAuth.Claims;
|
|
||||||
|
|
||||||
|
|
||||||
namespace InnovEnergy.App.Backend.Database;
|
namespace InnovEnergy.App.Backend.Database;
|
||||||
|
|
||||||
|
|
||||||
public static partial class Db
|
public static partial class Db
|
||||||
{
|
{
|
||||||
|
//Since we do not want to stress the memory in the VM a lot, we make a snapshot of the database every 100 transactions.
|
||||||
|
private static int _backupCounter = 0;
|
||||||
private static void Backup()
|
private static void Backup()
|
||||||
{
|
{
|
||||||
_backupCounter++;
|
_backupCounter++;
|
||||||
|
@ -65,6 +61,8 @@ public static partial class Db
|
||||||
public static Boolean Delete(UserAction actionToDelete)
|
public static Boolean Delete(UserAction actionToDelete)
|
||||||
{
|
{
|
||||||
var deleteSuccess = RunTransaction(DeleteAction);
|
var deleteSuccess = RunTransaction(DeleteAction);
|
||||||
|
|
||||||
|
|
||||||
if (deleteSuccess)
|
if (deleteSuccess)
|
||||||
Backup();
|
Backup();
|
||||||
return deleteSuccess;
|
return deleteSuccess;
|
||||||
|
@ -73,6 +71,7 @@ public static partial class Db
|
||||||
Boolean DeleteAction()
|
Boolean DeleteAction()
|
||||||
{
|
{
|
||||||
return UserActions.Delete(action => action.Id == actionToDelete.Id) >0;
|
return UserActions.Delete(action => action.Id == actionToDelete.Id) >0;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +85,7 @@ public static partial class Db
|
||||||
|
|
||||||
Boolean DeleteWarning()
|
Boolean DeleteWarning()
|
||||||
{
|
{
|
||||||
return Warnings.Delete(error => error.Id == warningToDelete.Id) >0;
|
return Warnings.Delete(warning => warning.Id == warningToDelete.Id) >0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,15 +99,14 @@ public static partial class Db
|
||||||
|
|
||||||
Boolean DeleteInstallationAndItsDependencies()
|
Boolean DeleteInstallationAndItsDependencies()
|
||||||
{
|
{
|
||||||
|
InstallationAccess.Delete(i => i.InstallationId == installation.Id);
|
||||||
if (installation.Product == 0)
|
if (installation.Product == 0)
|
||||||
{
|
{
|
||||||
InstallationAccess.Delete(i => i.InstallationId == installation.Id);
|
//For Salimax, delete the OrderNumber2Installation entries associated with this installation id.
|
||||||
OrderNumber2Installation.Delete(i => i.InstallationId == installation.Id);
|
OrderNumber2Installation.Delete(i => i.InstallationId == installation.Id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Installations.Delete(i => i.Id == installation.Id) > 0;
|
return Installations.Delete(i => i.Id == installation.Id) > 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +121,6 @@ public static partial class Db
|
||||||
{
|
{
|
||||||
FolderAccess .Delete(u => u.UserId == user.Id);
|
FolderAccess .Delete(u => u.UserId == user.Id);
|
||||||
InstallationAccess.Delete(u => u.UserId == user.Id);
|
InstallationAccess.Delete(u => u.UserId == user.Id);
|
||||||
|
|
||||||
return Users.Delete(u => u.Id == user.Id) > 0;
|
return Users.Delete(u => u.Id == user.Id) > 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
using InnovEnergy.App.Backend.DataTypes;
|
using InnovEnergy.App.Backend.DataTypes;
|
||||||
|
|
||||||
namespace InnovEnergy.App.Backend.Database;
|
namespace InnovEnergy.App.Backend.Database;
|
||||||
|
|
||||||
|
|
||||||
public static partial class Db
|
public static partial class Db
|
||||||
{
|
{
|
||||||
|
//We can execute the updates manually for each table, but we prefer the abstract way using Connection.Update method
|
||||||
|
//We pass an object as an argument and the Connection will connect this object with the corresponding table.
|
||||||
|
//The update is being done based on the primary id of the object.
|
||||||
|
|
||||||
private static Boolean Update(Object obj)
|
private static Boolean Update(Object obj)
|
||||||
{
|
{
|
||||||
var success = Connection.Update(obj) > 0;
|
var success = Connection.Update(obj) > 0;
|
||||||
|
@ -22,7 +25,6 @@ public static partial class Db
|
||||||
return Update(obj: error);
|
return Update(obj: error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static Boolean Update(Warning warning)
|
public static Boolean Update(Warning warning)
|
||||||
{
|
{
|
||||||
return Update(obj: warning);
|
return Update(obj: warning);
|
||||||
|
@ -44,4 +46,15 @@ public static partial class Db
|
||||||
|
|
||||||
return Update(obj: user);
|
return Update(obj: user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void UpdateAction(UserAction updatedAction)
|
||||||
|
{
|
||||||
|
var existingAction = UserActions.FirstOrDefault(action => action.Id == updatedAction.Id);
|
||||||
|
|
||||||
|
if (existingAction != null)
|
||||||
|
{
|
||||||
|
Update(updatedAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -26,9 +26,9 @@ public static class Program
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
RabbitMqManager.InitializeEnvironment();
|
RabbitMqManager.InitializeEnvironment();
|
||||||
RabbitMqManager.StartRabbitMqConsumer();
|
RabbitMqManager.StartRabbitMqConsumer().SupressAwaitWarning();
|
||||||
WebsocketManager.MonitorSalimaxInstallationTable();
|
WebsocketManager.MonitorSalimaxInstallationTable().SupressAwaitWarning();
|
||||||
WebsocketManager.MonitorSalidomoInstallationTable();
|
WebsocketManager.MonitorSalidomoInstallationTable().SupressAwaitWarning();
|
||||||
|
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
using System.Net;
|
|
||||||
using System.Net.Sockets;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using InnovEnergy.App.Backend.Database;
|
using InnovEnergy.App.Backend.Database;
|
||||||
using InnovEnergy.App.Backend.DataTypes;
|
using InnovEnergy.App.Backend.DataTypes;
|
||||||
|
using InnovEnergy.Lib.Utils;
|
||||||
using RabbitMQ.Client;
|
using RabbitMQ.Client;
|
||||||
using RabbitMQ.Client.Events;
|
using RabbitMQ.Client.Events;
|
||||||
using InnovEnergy.Lib.Mailer;
|
|
||||||
|
|
||||||
namespace InnovEnergy.App.Backend.Websockets;
|
namespace InnovEnergy.App.Backend.Websockets;
|
||||||
|
|
||||||
|
@ -59,23 +57,17 @@ public static class RabbitMqManager
|
||||||
{
|
{
|
||||||
Installation installation = Db.Installations.FirstOrDefault(f => f.Product == receivedStatusMessage.Product && f.S3BucketId == receivedStatusMessage.InstallationId);
|
Installation installation = Db.Installations.FirstOrDefault(f => f.Product == receivedStatusMessage.Product && f.S3BucketId == receivedStatusMessage.InstallationId);
|
||||||
int installationId = (int)installation.Id;
|
int installationId = (int)installation.Id;
|
||||||
|
//Console.WriteLine("received a message from rabbitmq\n");
|
||||||
//if (installationId == 138)
|
|
||||||
//{
|
|
||||||
// Console.WriteLine("Received a message from installation: " + installationId + " , product is: " + receivedStatusMessage.Product + " and status is: " + receivedStatusMessage.Status);
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//This is a heartbit message, just update the timestamp for this installation.
|
//This is a heartbit message, just update the timestamp for this installation.
|
||||||
//There is no need to notify the corresponding front-ends.
|
//There is no need to notify the corresponding front-ends.
|
||||||
//Every 15 iterations(30 seconds), the installation sends a heartbit message to the queue
|
//Every 15 iterations(30 seconds), the installation sends a heartbit message to the queue
|
||||||
if (receivedStatusMessage.Type == MessageType.Heartbit)
|
if (receivedStatusMessage.Type == MessageType.Heartbit)
|
||||||
{
|
{
|
||||||
if (installation.Product == 1 && installation.Device == 2)
|
// if (installation.Product == 1 && installation.Device == 2)
|
||||||
{
|
// {
|
||||||
Console.WriteLine("This is a heartbit message from installation: " + installationId + " Name of the file is " + receivedStatusMessage.Timestamp);
|
// Console.WriteLine("This is a heartbit message from installation: " + installationId + " Name of the file is " + receivedStatusMessage.Timestamp);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -95,7 +87,7 @@ public static class RabbitMqManager
|
||||||
Seen = false
|
Seen = false
|
||||||
};
|
};
|
||||||
//Create a new warning and add it to the database
|
//Create a new warning and add it to the database
|
||||||
Console.WriteLine("Add a warning for installation "+installationId);
|
//Console.WriteLine("Add a warning for installation "+installationId);
|
||||||
Db.HandleWarning(newWarning, installationId);
|
Db.HandleWarning(newWarning, installationId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,8 +168,16 @@ public static class RabbitMqManager
|
||||||
prevStatus = WebsocketManager.InstallationConnections[installationId].Status;
|
prevStatus = WebsocketManager.InstallationConnections[installationId].Status;
|
||||||
WebsocketManager.InstallationConnections[installationId].Status = receivedStatusMessage.Status;
|
WebsocketManager.InstallationConnections[installationId].Status = receivedStatusMessage.Status;
|
||||||
WebsocketManager.InstallationConnections[installationId].Timestamp = DateTime.Now;
|
WebsocketManager.InstallationConnections[installationId].Timestamp = DateTime.Now;
|
||||||
|
// if (installationId == 130)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine("prevStatus " + prevStatus + " , new status is: " + receivedStatusMessage.Status + " and status is: " + receivedStatusMessage.Status);
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
installation.Status = receivedStatusMessage.Status;
|
||||||
|
installation.Apply(Db.Update);
|
||||||
|
|
||||||
//Console.WriteLine("----------------------------------------------");
|
//Console.WriteLine("----------------------------------------------");
|
||||||
//If the status has changed, update all the connected front-ends regarding this installation
|
//If the status has changed, update all the connected front-ends regarding this installation
|
||||||
if(prevStatus != receivedStatusMessage.Status && WebsocketManager.InstallationConnections[installationId].Connections.Count > 0)
|
if(prevStatus != receivedStatusMessage.Status && WebsocketManager.InstallationConnections[installationId].Connections.Count > 0)
|
||||||
|
|
|
@ -19,32 +19,53 @@ public static class WebsocketManager
|
||||||
{
|
{
|
||||||
while (true){
|
while (true){
|
||||||
lock (InstallationConnections){
|
lock (InstallationConnections){
|
||||||
|
Console.WriteLine("MONITOR SALIMAX INSTALLATIONS\n");
|
||||||
foreach (var installationConnection in InstallationConnections){
|
foreach (var installationConnection in InstallationConnections){
|
||||||
if (installationConnection.Value.Product==0 && (DateTime.Now - installationConnection.Value.Timestamp) > TimeSpan.FromMinutes(1)){
|
|
||||||
|
if (installationConnection.Value.Product==0 && (DateTime.Now - installationConnection.Value.Timestamp) > TimeSpan.FromMinutes(2)){
|
||||||
|
|
||||||
|
Console.WriteLine("Installation ID is "+installationConnection.Key);
|
||||||
|
Console.WriteLine("installationConnection.Value.Timestamp is "+installationConnection.Value.Timestamp);
|
||||||
|
Console.WriteLine("diff is "+(DateTime.Now-installationConnection.Value.Timestamp));
|
||||||
|
|
||||||
installationConnection.Value.Status = -1;
|
installationConnection.Value.Status = -1;
|
||||||
Installation installation = Db.Installations.FirstOrDefault(f => f.Product == 0 && f.S3BucketId == installationConnection.Key);
|
Installation installation = Db.Installations.FirstOrDefault(f => f.Product == 0 && f.Id == installationConnection.Key);
|
||||||
installation.Status = -1;
|
installation.Status = -1;
|
||||||
installation.Apply(Db.Update);
|
installation.Apply(Db.Update);
|
||||||
if (installationConnection.Value.Connections.Count > 0){InformWebsocketsForInstallation(installationConnection.Key);}
|
if (installationConnection.Value.Connections.Count > 0){InformWebsocketsForInstallation(installationConnection.Key);}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Console.WriteLine("FINISHED MONITORING SALIMAX INSTALLATIONS\n");
|
||||||
}
|
}
|
||||||
await Task.Delay(TimeSpan.FromMinutes(2));
|
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task MonitorSalidomoInstallationTable()
|
public static async Task MonitorSalidomoInstallationTable()
|
||||||
{
|
{
|
||||||
while (true){
|
while (true){
|
||||||
|
Console.WriteLine("TRY TO LOCK FOR MONITOR SALIDOMO INSTALLATIONS\n");
|
||||||
lock (InstallationConnections){
|
lock (InstallationConnections){
|
||||||
|
Console.WriteLine("MONITOR SALIDOMO INSTALLATIONS\n");
|
||||||
foreach (var installationConnection in InstallationConnections){
|
foreach (var installationConnection in InstallationConnections){
|
||||||
|
Console.WriteLine("Installation ID is "+installationConnection.Key);
|
||||||
|
|
||||||
|
|
||||||
|
// if (installationConnection.Key == 104)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine("installationConnection.Value.Timestamp is "+installationConnection.Value.Timestamp);
|
||||||
|
// Console.WriteLine("diff is "+(DateTime.Now-installationConnection.Value.Timestamp));
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// }
|
||||||
if (installationConnection.Value.Product==1 && (DateTime.Now - installationConnection.Value.Timestamp) > TimeSpan.FromMinutes(30))
|
if (installationConnection.Value.Product==1 && (DateTime.Now - installationConnection.Value.Timestamp) > TimeSpan.FromMinutes(30))
|
||||||
{
|
{
|
||||||
// Console.WriteLine("Installation ID is "+installationConnection.Key);
|
// Console.WriteLine("Installation ID is "+installationConnection.Key);
|
||||||
// Console.WriteLine("installationConnection.Value.Timestamp is "+installationConnection.Value.Timestamp);
|
// Console.WriteLine("installationConnection.Value.Timestamp is "+installationConnection.Value.Timestamp);
|
||||||
// Console.WriteLine("diff is "+(DateTime.Now-installationConnection.Value.Timestamp));
|
// Console.WriteLine("diff is "+(DateTime.Now-installationConnection.Value.Timestamp));
|
||||||
|
|
||||||
Installation installation = Db.Installations.FirstOrDefault(f => f.Product == 1 && f.S3BucketId == installationConnection.Key);
|
Installation installation = Db.Installations.FirstOrDefault(f => f.Product == 1 && f.Id == installationConnection.Key);
|
||||||
installation.Status = -1;
|
installation.Status = -1;
|
||||||
installation.Apply(Db.Update);
|
installation.Apply(Db.Update);
|
||||||
|
|
||||||
|
@ -52,8 +73,9 @@ public static class WebsocketManager
|
||||||
if (installationConnection.Value.Connections.Count > 0){InformWebsocketsForInstallation(installationConnection.Key);}
|
if (installationConnection.Value.Connections.Count > 0){InformWebsocketsForInstallation(installationConnection.Key);}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Console.WriteLine("FINISHED WITH UPDATING\n");
|
||||||
}
|
}
|
||||||
await Task.Delay(TimeSpan.FromMinutes(10));
|
await Task.Delay(TimeSpan.FromMinutes(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,7 +146,6 @@ public static class WebsocketManager
|
||||||
//Console.WriteLine("Received a new message from websocket");
|
//Console.WriteLine("Received a new message from websocket");
|
||||||
lock (InstallationConnections)
|
lock (InstallationConnections)
|
||||||
{
|
{
|
||||||
|
|
||||||
List<WebsocketMessage> dataToSend = new List<WebsocketMessage>();
|
List<WebsocketMessage> dataToSend = new List<WebsocketMessage>();
|
||||||
|
|
||||||
//Each front-end will send the list of the installations it wants to access
|
//Each front-end will send the list of the installations it wants to access
|
||||||
|
@ -139,7 +160,7 @@ public static class WebsocketManager
|
||||||
//Console.WriteLine("Create new empty list for installation id " + installationId);
|
//Console.WriteLine("Create new empty list for installation id " + installationId);
|
||||||
InstallationConnections[installationId] = new InstallationInfo
|
InstallationConnections[installationId] = new InstallationInfo
|
||||||
{
|
{
|
||||||
Status = -1,
|
Status = installation.Status,
|
||||||
Product = installation.Product
|
Product = installation.Product
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -155,15 +176,6 @@ public static class WebsocketManager
|
||||||
|
|
||||||
dataToSend.Add(jsonObject);
|
dataToSend.Add(jsonObject);
|
||||||
|
|
||||||
//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
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
var jsonString = JsonSerializer.Serialize(dataToSend);
|
var jsonString = JsonSerializer.Serialize(dataToSend);
|
||||||
var encodedDataToSend = Encoding.UTF8.GetBytes(jsonString);
|
var encodedDataToSend = Encoding.UTF8.GetBytes(jsonString);
|
||||||
|
|
|
@ -13,9 +13,9 @@ DEVICE_INSTANCE = 1
|
||||||
SERVICE_NAME_PREFIX = 'com.victronenergy.battery.'
|
SERVICE_NAME_PREFIX = 'com.victronenergy.battery.'
|
||||||
|
|
||||||
#s3 configuration
|
#s3 configuration
|
||||||
S3BUCKET = "673-c0436b6a-d276-4cd8-9c44-1eae86cf5d0e"
|
S3BUCKET = "489-c0436b6a-d276-4cd8-9c44-1eae86cf5d0e"
|
||||||
S3KEY = "EXO270612dc3f57a61870220eea"
|
S3KEY = "EXOd55ec2d5702c3b94f1e275a4"
|
||||||
S3SECRET = "4fPVVN8JGnD9IY1k5RrrNUzo2L1IpR6gdSuGRB9pMWg"
|
S3SECRET = "0bOJW6COdJ1_vQ_SDbaYKtLs9E7bxANZb5d1X4zf97g"
|
||||||
|
|
||||||
# driver configuration
|
# driver configuration
|
||||||
|
|
||||||
|
|
|
@ -643,6 +643,10 @@ def read_battery_status(modbus, battery):
|
||||||
modbus.connect()
|
modbus.connect()
|
||||||
data = read_modbus_registers(modbus, battery.slave_address)
|
data = read_modbus_registers(modbus, battery.slave_address)
|
||||||
return BatteryStatus(battery, data.registers)
|
return BatteryStatus(battery, data.registers)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"An error occurred: {e}")
|
||||||
|
create_batch_of_csv_files() # Call this only if there's an error
|
||||||
|
raise
|
||||||
finally:
|
finally:
|
||||||
modbus.close() # close in any case
|
modbus.close() # close in any case
|
||||||
|
|
||||||
|
@ -655,6 +659,7 @@ def publish_values(dbus, signals, statuses):
|
||||||
|
|
||||||
previous_warnings = {}
|
previous_warnings = {}
|
||||||
previous_alarms = {}
|
previous_alarms = {}
|
||||||
|
num_of_csv_files_saved=0
|
||||||
|
|
||||||
class MessageType:
|
class MessageType:
|
||||||
ALARM_OR_WARNING = "AlarmOrWarning"
|
ALARM_OR_WARNING = "AlarmOrWarning"
|
||||||
|
@ -680,6 +685,7 @@ def SubscribeToQueue():
|
||||||
connection = pika.BlockingConnection(pika.ConnectionParameters(host="10.2.0.11",
|
connection = pika.BlockingConnection(pika.ConnectionParameters(host="10.2.0.11",
|
||||||
port=5672,
|
port=5672,
|
||||||
virtual_host="/",
|
virtual_host="/",
|
||||||
|
heartbeat=30,
|
||||||
credentials=pika.PlainCredentials("producer", "b187ceaddb54d5485063ddc1d41af66f")))
|
credentials=pika.PlainCredentials("producer", "b187ceaddb54d5485063ddc1d41af66f")))
|
||||||
channel = connection.channel()
|
channel = connection.channel()
|
||||||
channel.queue_declare(queue="statusQueue", durable=True)
|
channel.queue_declare(queue="statusQueue", durable=True)
|
||||||
|
@ -903,7 +909,7 @@ def count_files_in_folder(folder_path):
|
||||||
|
|
||||||
def create_batch_of_csv_files():
|
def create_batch_of_csv_files():
|
||||||
|
|
||||||
global prev_status,INSTALLATION_ID, PRODUCT_ID
|
global prev_status,INSTALLATION_ID, PRODUCT_ID, num_of_csv_files_saved
|
||||||
# list all files in the directory
|
# list all files in the directory
|
||||||
files = os.listdir(CSV_DIR)
|
files = os.listdir(CSV_DIR)
|
||||||
|
|
||||||
|
@ -914,7 +920,8 @@ def create_batch_of_csv_files():
|
||||||
csv_files.sort(key=lambda x: os.path.getctime(os.path.join(CSV_DIR, x)))
|
csv_files.sort(key=lambda x: os.path.getctime(os.path.join(CSV_DIR, x)))
|
||||||
|
|
||||||
# keep the 600 MOST RECENT FILES
|
# keep the 600 MOST RECENT FILES
|
||||||
recent_csv_files = csv_files[-600:] if len(csv_files) > 600 else csv_files
|
recent_csv_files = csv_files[-num_of_csv_files_saved:]
|
||||||
|
print("num_of_csv_files_saved is " + str(num_of_csv_files_saved))
|
||||||
|
|
||||||
# get the name of the first csv file
|
# get the name of the first csv file
|
||||||
if not csv_files:
|
if not csv_files:
|
||||||
|
@ -949,6 +956,7 @@ def create_batch_of_csv_files():
|
||||||
# replace the original first csv file with the temporary file
|
# replace the original first csv file with the temporary file
|
||||||
os.remove(first_csv_file)
|
os.remove(first_csv_file)
|
||||||
os.rename(temp_file_path, first_csv_file)
|
os.rename(temp_file_path, first_csv_file)
|
||||||
|
num_of_csv_files_saved = 0
|
||||||
|
|
||||||
# create a loggin directory that contains at max 20 batch files for logging info
|
# create a loggin directory that contains at max 20 batch files for logging info
|
||||||
# logging_dir = os.path.join(CSV_DIR, 'logging_batch_files')
|
# logging_dir = os.path.join(CSV_DIR, 'logging_batch_files')
|
||||||
|
@ -1023,10 +1031,12 @@ def create_update_task(modbus, dbus, batteries, signals, csv_signals, main_loop)
|
||||||
ALLOW = True
|
ALLOW = True
|
||||||
alive = update(modbus, batteries, dbus, signals, csv_signals)
|
alive = update(modbus, batteries, dbus, signals, csv_signals)
|
||||||
elapsed_time = time.time() - start_time
|
elapsed_time = time.time() - start_time
|
||||||
|
print("11111111111111111111111111111111111111111111 elapsed time is ", elapsed_time)
|
||||||
|
|
||||||
# keep at most 1900 files at CSV_DIR for logging and aggregation
|
# keep at most 1900 files at CSV_DIR for logging and aggregation
|
||||||
manage_csv_files(CSV_DIR, 1900)
|
manage_csv_files(CSV_DIR, 1900)
|
||||||
if elapsed_time >= 1200:
|
if elapsed_time >= 1200:
|
||||||
|
print("CREATE BATCH ======================================>")
|
||||||
create_batch_of_csv_files()
|
create_batch_of_csv_files()
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
#alive = update_for_testing(modbus, batteries, dbus, signals, csv_signals)
|
#alive = update_for_testing(modbus, batteries, dbus, signals, csv_signals)
|
||||||
|
@ -1075,7 +1085,7 @@ def insert_id(path, id_number):
|
||||||
return "/".join(parts)
|
return "/".join(parts)
|
||||||
|
|
||||||
def create_csv_files(signals, statuses, node_numbers, alarms_number_list, warnings_number_list):
|
def create_csv_files(signals, statuses, node_numbers, alarms_number_list, warnings_number_list):
|
||||||
global s3_config
|
global s3_config, num_of_csv_files_saved
|
||||||
timestamp = int(time.time())
|
timestamp = int(time.time())
|
||||||
if timestamp % 2 != 0:
|
if timestamp % 2 != 0:
|
||||||
timestamp -= 1
|
timestamp -= 1
|
||||||
|
@ -1084,6 +1094,8 @@ def create_csv_files(signals, statuses, node_numbers, alarms_number_list, warnin
|
||||||
os.makedirs(CSV_DIR)
|
os.makedirs(CSV_DIR)
|
||||||
csv_filename = f"{timestamp}.csv"
|
csv_filename = f"{timestamp}.csv"
|
||||||
csv_path = os.path.join(CSV_DIR, csv_filename)
|
csv_path = os.path.join(CSV_DIR, csv_filename)
|
||||||
|
num_of_csv_files_saved+=1
|
||||||
|
|
||||||
# Append values to the CSV file
|
# Append values to the CSV file
|
||||||
if not os.path.exists(csv_path):
|
if not os.path.exists(csv_path):
|
||||||
with open(csv_path, 'a', newline='') as csvfile:
|
with open(csv_path, 'a', newline='') as csvfile:
|
||||||
|
|
|
@ -54,6 +54,6 @@ INNOVENERGY_PROTOCOL_VERSION = '48TL200V3'
|
||||||
|
|
||||||
|
|
||||||
# S3 Credentials
|
# S3 Credentials
|
||||||
S3BUCKET = "140-c0436b6a-d276-4cd8-9c44-1eae86cf5d0e"
|
S3BUCKET = "627-c0436b6a-d276-4cd8-9c44-1eae86cf5d0e"
|
||||||
S3KEY = "EXOa947c7fc5990a7a6f6c40860"
|
S3KEY = "EXOb7bcf7d1e53f2d46923144de"
|
||||||
S3SECRET = "J1yOTLbYEO6cMxQ2wgIwe__ru9-_RH5BBtKzx_2JJHk"
|
S3SECRET = "-uUmMuAfx40LpTKTZgdbXswTw09o_qmE4gzkmQS8PTk"
|
||||||
|
|
|
@ -33,6 +33,7 @@ import io
|
||||||
import json
|
import json
|
||||||
from convert import first
|
from convert import first
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
CSV_DIR = "/data/csv_files/"
|
CSV_DIR = "/data/csv_files/"
|
||||||
INSTALLATION_NAME_FILE = '/data/innovenergy/openvpn/installation-name'
|
INSTALLATION_NAME_FILE = '/data/innovenergy/openvpn/installation-name'
|
||||||
|
|
||||||
|
@ -41,7 +42,6 @@ INSTALLATION_NAME_FILE = '/data/innovenergy/openvpn/installation-name'
|
||||||
if False:
|
if False:
|
||||||
from typing import Callable, List, Iterable, NoReturn
|
from typing import Callable, List, Iterable, NoReturn
|
||||||
|
|
||||||
|
|
||||||
RESET_REGISTER = 0x2087
|
RESET_REGISTER = 0x2087
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ def compress_csv_data(csv_data, file_name="data.csv"):
|
||||||
|
|
||||||
return base64_string
|
return base64_string
|
||||||
|
|
||||||
|
|
||||||
class S3config:
|
class S3config:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.bucket = cfg.S3BUCKET
|
self.bucket = cfg.S3BUCKET
|
||||||
|
@ -111,7 +112,9 @@ def SubscribeToQueue():
|
||||||
connection = pika.BlockingConnection(pika.ConnectionParameters(host="10.2.0.11",
|
connection = pika.BlockingConnection(pika.ConnectionParameters(host="10.2.0.11",
|
||||||
port=5672,
|
port=5672,
|
||||||
virtual_host="/",
|
virtual_host="/",
|
||||||
credentials=pika.PlainCredentials("producer", "b187ceaddb54d5485063ddc1d41af66f")))
|
heartbeat=30,
|
||||||
|
credentials=pika.PlainCredentials("producer",
|
||||||
|
"b187ceaddb54d5485063ddc1d41af66f")))
|
||||||
channel = connection.channel()
|
channel = connection.channel()
|
||||||
channel.queue_declare(queue="statusQueue", durable=True)
|
channel.queue_declare(queue="statusQueue", durable=True)
|
||||||
print("Subscribed to queue")
|
print("Subscribed to queue")
|
||||||
|
@ -123,10 +126,12 @@ def SubscribeToQueue():
|
||||||
previous_warnings = {}
|
previous_warnings = {}
|
||||||
previous_alarms = {}
|
previous_alarms = {}
|
||||||
|
|
||||||
|
|
||||||
class MessageType:
|
class MessageType:
|
||||||
ALARM_OR_WARNING = "AlarmOrWarning"
|
ALARM_OR_WARNING = "AlarmOrWarning"
|
||||||
HEARTBEAT = "Heartbeat"
|
HEARTBEAT = "Heartbeat"
|
||||||
|
|
||||||
|
|
||||||
class AlarmOrWarning:
|
class AlarmOrWarning:
|
||||||
def __init__(self, description, created_by):
|
def __init__(self, description, created_by):
|
||||||
self.date = datetime.now().strftime('%Y-%m-%d')
|
self.date = datetime.now().strftime('%Y-%m-%d')
|
||||||
|
@ -142,13 +147,16 @@ class AlarmOrWarning:
|
||||||
"CreatedBy": self.created_by
|
"CreatedBy": self.created_by
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
channel = SubscribeToQueue()
|
channel = SubscribeToQueue()
|
||||||
# Create an S3config instance
|
# Create an S3config instance
|
||||||
s3_config = S3config()
|
s3_config = S3config()
|
||||||
INSTALLATION_ID=int(s3_config.bucket.split('-')[0])
|
INSTALLATION_ID = int(s3_config.bucket.split('-')[0])
|
||||||
PRODUCT_ID = 1
|
PRODUCT_ID = 1
|
||||||
is_first_update = True
|
is_first_update = True
|
||||||
prev_status = 0
|
prev_status = 0
|
||||||
|
num_of_csv_files_saved = 0
|
||||||
|
|
||||||
|
|
||||||
def update_state_from_dictionaries(current_warnings, current_alarms, node_numbers):
|
def update_state_from_dictionaries(current_warnings, current_alarms, node_numbers):
|
||||||
global previous_warnings, previous_alarms, INSTALLATION_ID, PRODUCT_ID, is_first_update, channel, prev_status
|
global previous_warnings, previous_alarms, INSTALLATION_ID, PRODUCT_ID, is_first_update, channel, prev_status
|
||||||
|
@ -192,17 +200,16 @@ def update_state_from_dictionaries(current_warnings, current_alarms, node_number
|
||||||
for i, alarm_value in enumerate(current_alarms.values()):
|
for i, alarm_value in enumerate(current_alarms.values()):
|
||||||
if int(list(current_alarms.keys())[i].split("/")[3]) == int(node_number):
|
if int(list(current_alarms.keys())[i].split("/")[3]) == int(node_number):
|
||||||
if alarm_value:
|
if alarm_value:
|
||||||
cnt+=1
|
cnt += 1
|
||||||
alarms_number_list.append(cnt)
|
alarms_number_list.append(cnt)
|
||||||
|
|
||||||
|
|
||||||
warnings_number_list = []
|
warnings_number_list = []
|
||||||
for node_number in node_numbers:
|
for node_number in node_numbers:
|
||||||
cnt = 0
|
cnt = 0
|
||||||
for i, warning_value in enumerate(current_warnings.values()):
|
for i, warning_value in enumerate(current_warnings.values()):
|
||||||
if int(list(current_warnings.keys())[i].split("/")[3]) == int(node_number):
|
if int(list(current_warnings.keys())[i].split("/")[3]) == int(node_number):
|
||||||
if warning_value:
|
if warning_value:
|
||||||
cnt+=1
|
cnt += 1
|
||||||
warnings_number_list.append(cnt)
|
warnings_number_list.append(cnt)
|
||||||
|
|
||||||
# Evaluate alarms
|
# Evaluate alarms
|
||||||
|
@ -221,17 +228,18 @@ def update_state_from_dictionaries(current_warnings, current_alarms, node_number
|
||||||
status_message["Warnings"].append(AlarmOrWarning(description, device_created).to_dict())
|
status_message["Warnings"].append(AlarmOrWarning(description, device_created).to_dict())
|
||||||
|
|
||||||
if any(current_alarms.values()):
|
if any(current_alarms.values()):
|
||||||
status_message["Status"]=2
|
status_message["Status"] = 2
|
||||||
|
|
||||||
if not any(current_alarms.values()) and any(current_warnings.values()):
|
if not any(current_alarms.values()) and any(current_warnings.values()):
|
||||||
status_message["Status"]=1
|
status_message["Status"] = 1
|
||||||
|
|
||||||
if not any(current_alarms.values()) and not any(current_warnings.values()):
|
if not any(current_alarms.values()) and not any(current_warnings.values()):
|
||||||
status_message["Status"]=0
|
status_message["Status"] = 0
|
||||||
|
|
||||||
if status_message["Status"]!=prev_status or len(status_message["Warnings"])>0 or len(status_message["Alarms"])>0:
|
if status_message["Status"] != prev_status or len(status_message["Warnings"]) > 0 or len(
|
||||||
prev_status=status_message["Status"]
|
status_message["Alarms"]) > 0:
|
||||||
status_message["Type"]=0
|
prev_status = status_message["Status"]
|
||||||
|
status_message["Type"] = 0
|
||||||
status_message = json.dumps(status_message)
|
status_message = json.dumps(status_message)
|
||||||
channel.basic_publish(exchange="", routing_key="statusQueue", body=status_message)
|
channel.basic_publish(exchange="", routing_key="statusQueue", body=status_message)
|
||||||
print(status_message)
|
print(status_message)
|
||||||
|
@ -242,6 +250,7 @@ def update_state_from_dictionaries(current_warnings, current_alarms, node_number
|
||||||
|
|
||||||
return status_message, alarms_number_list, warnings_number_list
|
return status_message, alarms_number_list, warnings_number_list
|
||||||
|
|
||||||
|
|
||||||
def read_csv_as_string(file_path):
|
def read_csv_as_string(file_path):
|
||||||
"""
|
"""
|
||||||
Reads a CSV file from the given path and returns its content as a single string.
|
Reads a CSV file from the given path and returns its content as a single string.
|
||||||
|
@ -259,7 +268,6 @@ def read_csv_as_string(file_path):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def init_modbus(tty):
|
def init_modbus(tty):
|
||||||
# type: (str) -> Modbus
|
# type: (str) -> Modbus
|
||||||
|
|
||||||
|
@ -292,7 +300,6 @@ def report_slave_id(modbus, slave_address):
|
||||||
logging.debug('requesting slave id from node ' + slave)
|
logging.debug('requesting slave id from node ' + slave)
|
||||||
|
|
||||||
with modbus:
|
with modbus:
|
||||||
|
|
||||||
request = ReportSlaveIdRequest(unit=slave_address)
|
request = ReportSlaveIdRequest(unit=slave_address)
|
||||||
response = modbus.execute(request)
|
response = modbus.execute(request)
|
||||||
|
|
||||||
|
@ -369,7 +376,6 @@ def read_firmware_version(modbus, slave_address):
|
||||||
logging.debug('reading firmware version')
|
logging.debug('reading firmware version')
|
||||||
|
|
||||||
with modbus:
|
with modbus:
|
||||||
|
|
||||||
response = read_modbus_registers(modbus, slave_address, base_address=1054, count=1)
|
response = read_modbus_registers(modbus, slave_address, base_address=1054, count=1)
|
||||||
register = response.registers[0]
|
register = response.registers[0]
|
||||||
|
|
||||||
|
@ -452,8 +458,8 @@ def upload_status_to_innovenergy(sock, statuses):
|
||||||
|
|
||||||
|
|
||||||
def print_usage():
|
def print_usage():
|
||||||
print ('Usage: ' + __file__ + ' <serial device>')
|
print('Usage: ' + __file__ + ' <serial device>')
|
||||||
print ('Example: ' + __file__ + ' ttyUSB0')
|
print('Example: ' + __file__ + ' ttyUSB0')
|
||||||
|
|
||||||
|
|
||||||
def parse_cmdline_args(argv):
|
def parse_cmdline_args(argv):
|
||||||
|
@ -473,7 +479,6 @@ def reset_batteries(modbus, batteries):
|
||||||
logging.info('Resetting batteries...')
|
logging.info('Resetting batteries...')
|
||||||
|
|
||||||
for battery in batteries:
|
for battery in batteries:
|
||||||
|
|
||||||
result = modbus.write_registers(RESET_REGISTER, [1], unit=battery.slave_address)
|
result = modbus.write_registers(RESET_REGISTER, [1], unit=battery.slave_address)
|
||||||
|
|
||||||
# expecting a ModbusIOException (timeout)
|
# expecting a ModbusIOException (timeout)
|
||||||
|
@ -490,6 +495,8 @@ def reset_batteries(modbus, batteries):
|
||||||
alive = True # global alive flag, watchdog_task clears it, update_task sets it
|
alive = True # global alive flag, watchdog_task clears it, update_task sets it
|
||||||
|
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
||||||
|
|
||||||
def count_files_in_folder(folder_path):
|
def count_files_in_folder(folder_path):
|
||||||
try:
|
try:
|
||||||
# List all files in the folder
|
# List all files in the folder
|
||||||
|
@ -521,8 +528,8 @@ def create_update_task(modbus, service, batteries):
|
||||||
|
|
||||||
def update_task():
|
def update_task():
|
||||||
# type: () -> bool
|
# type: () -> bool
|
||||||
global alive, start_time
|
try:
|
||||||
|
global alive, start_time, channel
|
||||||
logging.debug('starting update cycle')
|
logging.debug('starting update cycle')
|
||||||
|
|
||||||
if service.own_properties.get('/ResetBatteries').value == 1:
|
if service.own_properties.get('/ResetBatteries').value == 1:
|
||||||
|
@ -549,7 +556,7 @@ def create_update_task(modbus, service, batteries):
|
||||||
|
|
||||||
elapsed_time = time.time() - start_time
|
elapsed_time = time.time() - start_time
|
||||||
create_csv_files(csv_signals, statuses, node_numbers, alarms_number_list, warnings_number_list)
|
create_csv_files(csv_signals, statuses, node_numbers, alarms_number_list, warnings_number_list)
|
||||||
print("11111111111111111111111111111111111111111111 elapsed time is ",elapsed_time)
|
print("11111111111111111111111111111111111111111111 elapsed time is ", elapsed_time)
|
||||||
|
|
||||||
# keep at most 1900 files at CSV_DIR for logging and aggregation
|
# keep at most 1900 files at CSV_DIR for logging and aggregation
|
||||||
manage_csv_files(CSV_DIR, 1900)
|
manage_csv_files(CSV_DIR, 1900)
|
||||||
|
@ -562,31 +569,44 @@ def create_update_task(modbus, service, batteries):
|
||||||
|
|
||||||
upload_status_to_innovenergy(_socket, statuses)
|
upload_status_to_innovenergy(_socket, statuses)
|
||||||
|
|
||||||
# logging.debug('finished update cycleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n')
|
# logging.debug('finished update cycleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n')
|
||||||
|
|
||||||
alive = True
|
alive = True
|
||||||
|
except pika.exceptions.AMQPConnectionError:
|
||||||
|
logging.error("AMQPConnectionError encountered. Subscribing to queue.")
|
||||||
|
create_batch_of_csv_files()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
create_batch_of_csv_files()
|
||||||
|
logging.error("Unexpected error")
|
||||||
|
raise
|
||||||
|
|
||||||
|
finally:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return update_task
|
return update_task
|
||||||
|
|
||||||
|
|
||||||
def manage_csv_files(directory_path, max_files=20):
|
def manage_csv_files(directory_path, max_files=20):
|
||||||
csv_files = [f for f in os.listdir(directory_path) if os.path.isfile(os.path.join(directory_path, f))]
|
csv_files = [f for f in os.listdir(directory_path) if os.path.isfile(os.path.join(directory_path, f))]
|
||||||
csv_files.sort(key=lambda x: os.path.getctime(os.path.join(directory_path, x)))
|
csv_files.sort(key=lambda x: os.path.getctime(os.path.join(directory_path, x)))
|
||||||
|
|
||||||
print("len of csv files is "+str(len(csv_files)))
|
print("len of csv files is " + str(len(csv_files)))
|
||||||
# Remove oldest files if exceeds maximum
|
# Remove oldest files if exceeds maximum
|
||||||
while len(csv_files) > max_files:
|
while len(csv_files) > max_files:
|
||||||
file_to_delete = os.path.join(directory_path, csv_files.pop(0))
|
file_to_delete = os.path.join(directory_path, csv_files.pop(0))
|
||||||
os.remove(file_to_delete)
|
os.remove(file_to_delete)
|
||||||
|
|
||||||
|
|
||||||
def insert_id(path, id_number):
|
def insert_id(path, id_number):
|
||||||
parts = path.split("/")
|
parts = path.split("/")
|
||||||
insert_position = parts.index("Devices") + 1
|
insert_position = parts.index("Devices") + 1
|
||||||
parts.insert(insert_position, str(id_number))
|
parts.insert(insert_position, str(id_number))
|
||||||
return "/".join(parts)
|
return "/".join(parts)
|
||||||
|
|
||||||
|
|
||||||
def create_batch_of_csv_files():
|
def create_batch_of_csv_files():
|
||||||
global prev_status,channel,INSTALLATION_ID, PRODUCT_ID
|
global prev_status, channel, INSTALLATION_ID, PRODUCT_ID, num_of_csv_files_saved
|
||||||
# list all files in the directory
|
# list all files in the directory
|
||||||
files = os.listdir(CSV_DIR)
|
files = os.listdir(CSV_DIR)
|
||||||
|
|
||||||
|
@ -596,8 +616,9 @@ def create_batch_of_csv_files():
|
||||||
# sort csv files by creation time
|
# sort csv files by creation time
|
||||||
csv_files.sort(key=lambda x: os.path.getctime(os.path.join(CSV_DIR, x)))
|
csv_files.sort(key=lambda x: os.path.getctime(os.path.join(CSV_DIR, x)))
|
||||||
|
|
||||||
# keep the 600 MOST RECENT FILES
|
# keep the num_of_csv_files_saved MOST RECENT FILES
|
||||||
recent_csv_files = csv_files[-600:] if len(csv_files) > 600 else csv_files
|
recent_csv_files = csv_files[-num_of_csv_files_saved:]
|
||||||
|
print("num_of_csv_files_saved is " + str(num_of_csv_files_saved))
|
||||||
|
|
||||||
# get the name of the first csv file
|
# get the name of the first csv file
|
||||||
if not csv_files:
|
if not csv_files:
|
||||||
|
@ -629,6 +650,7 @@ def create_batch_of_csv_files():
|
||||||
# replace the original first csv file with the temporary file
|
# replace the original first csv file with the temporary file
|
||||||
os.remove(first_csv_file)
|
os.remove(first_csv_file)
|
||||||
os.rename(temp_file_path, first_csv_file)
|
os.rename(temp_file_path, first_csv_file)
|
||||||
|
num_of_csv_files_saved = 0
|
||||||
|
|
||||||
# create a loggin directory that contains at max 20 batch files for logging info
|
# create a loggin directory that contains at max 20 batch files for logging info
|
||||||
# logging_dir = os.path.join(CSV_DIR, 'logging_batch_files')
|
# logging_dir = os.path.join(CSV_DIR, 'logging_batch_files')
|
||||||
|
@ -647,7 +669,6 @@ def create_batch_of_csv_files():
|
||||||
print("error while reading csv as string")
|
print("error while reading csv as string")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
# zip-comp additions
|
# zip-comp additions
|
||||||
compressed_csv = compress_csv_data(csv_data)
|
compressed_csv = compress_csv_data(csv_data)
|
||||||
# Use the name of the last (most recent) CSV file in sorted csv_files as the name for the compressed file
|
# Use the name of the last (most recent) CSV file in sorted csv_files as the name for the compressed file
|
||||||
|
@ -686,7 +707,6 @@ def create_batch_of_csv_files():
|
||||||
channel = SubscribeToQueue()
|
channel = SubscribeToQueue()
|
||||||
channel.basic_publish(exchange="", routing_key="statusQueue", body=status_message)
|
channel.basic_publish(exchange="", routing_key="statusQueue", body=status_message)
|
||||||
|
|
||||||
|
|
||||||
print("Successfully sent the heartbit with timestamp")
|
print("Successfully sent the heartbit with timestamp")
|
||||||
else:
|
else:
|
||||||
# we save data that were not successfully uploaded in s3 in a failed directory inside the CSV_DIR for logging
|
# we save data that were not successfully uploaded in s3 in a failed directory inside the CSV_DIR for logging
|
||||||
|
@ -698,7 +718,9 @@ def create_batch_of_csv_files():
|
||||||
print("Uploading failed")
|
print("Uploading failed")
|
||||||
manage_csv_files(failed_dir, 100)
|
manage_csv_files(failed_dir, 100)
|
||||||
|
|
||||||
|
|
||||||
def create_csv_files(signals, statuses, node_numbers, alarms_number_list, warnings_number_list):
|
def create_csv_files(signals, statuses, node_numbers, alarms_number_list, warnings_number_list):
|
||||||
|
global num_of_csv_files_saved
|
||||||
timestamp = int(time.time())
|
timestamp = int(time.time())
|
||||||
if timestamp % 2 != 0:
|
if timestamp % 2 != 0:
|
||||||
timestamp -= 1
|
timestamp -= 1
|
||||||
|
@ -706,6 +728,7 @@ def create_csv_files(signals, statuses, node_numbers, alarms_number_list, warnin
|
||||||
os.makedirs(CSV_DIR)
|
os.makedirs(CSV_DIR)
|
||||||
csv_filename = "{}.csv".format(timestamp)
|
csv_filename = "{}.csv".format(timestamp)
|
||||||
csv_path = os.path.join(CSV_DIR, csv_filename)
|
csv_path = os.path.join(CSV_DIR, csv_filename)
|
||||||
|
num_of_csv_files_saved += 1
|
||||||
|
|
||||||
if not os.path.exists(csv_path):
|
if not os.path.exists(csv_path):
|
||||||
with open(csv_path, 'ab') as csvfile:
|
with open(csv_path, 'ab') as csvfile:
|
||||||
|
@ -715,14 +738,15 @@ def create_csv_files(signals, statuses, node_numbers, alarms_number_list, warnin
|
||||||
config_row = [nodes_config_path, nodes_list, ""]
|
config_row = [nodes_config_path, nodes_list, ""]
|
||||||
csv_writer.writerow(config_row)
|
csv_writer.writerow(config_row)
|
||||||
for i, node in enumerate(node_numbers):
|
for i, node in enumerate(node_numbers):
|
||||||
csv_writer.writerow(["/Battery/Devices/{}/Alarms".format(str(i+1)), alarms_number_list[i], ""])
|
csv_writer.writerow(["/Battery/Devices/{}/Alarms".format(str(i + 1)), alarms_number_list[i], ""])
|
||||||
csv_writer.writerow(["/Battery/Devices/{}/Warnings".format(str(i+1)), warnings_number_list[i], ""])
|
csv_writer.writerow(["/Battery/Devices/{}/Warnings".format(str(i + 1)), warnings_number_list[i], ""])
|
||||||
for s in signals:
|
for s in signals:
|
||||||
signal_name = insert_id(s.name, i+1)
|
signal_name = insert_id(s.name, i + 1)
|
||||||
value = s.get_value(statuses[i])
|
value = s.get_value(statuses[i])
|
||||||
row_values = [signal_name, value, s.get_text]
|
row_values = [signal_name, value, s.get_text]
|
||||||
csv_writer.writerow(row_values)
|
csv_writer.writerow(row_values)
|
||||||
|
|
||||||
|
|
||||||
def create_watchdog_task(main_loop):
|
def create_watchdog_task(main_loop):
|
||||||
# type: (DBusGMainLoop) -> Callable[[],bool]
|
# type: (DBusGMainLoop) -> Callable[[],bool]
|
||||||
"""
|
"""
|
||||||
|
@ -730,6 +754,7 @@ def create_watchdog_task(main_loop):
|
||||||
The watchdog kills the main loop if the alive flag is not periodically reset by the update task.
|
The watchdog kills the main loop if the alive flag is not periodically reset by the update task.
|
||||||
Who watches the watchdog?
|
Who watches the watchdog?
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def watchdog_task():
|
def watchdog_task():
|
||||||
# type: () -> bool
|
# type: () -> bool
|
||||||
|
|
||||||
|
@ -746,7 +771,10 @@ def create_watchdog_task(main_loop):
|
||||||
|
|
||||||
return watchdog_task
|
return watchdog_task
|
||||||
|
|
||||||
|
|
||||||
BATTERY_COUNTS_FILE = '/data/battery_count.csv'
|
BATTERY_COUNTS_FILE = '/data/battery_count.csv'
|
||||||
|
|
||||||
|
|
||||||
def load_battery_counts():
|
def load_battery_counts():
|
||||||
if os.path.exists(BATTERY_COUNTS_FILE):
|
if os.path.exists(BATTERY_COUNTS_FILE):
|
||||||
with open(BATTERY_COUNTS_FILE, 'r') as f:
|
with open(BATTERY_COUNTS_FILE, 'r') as f:
|
||||||
|
@ -760,6 +788,8 @@ def save_battery_counts(battery_counts):
|
||||||
writer = csv.writer(f)
|
writer = csv.writer(f)
|
||||||
for count in battery_counts:
|
for count in battery_counts:
|
||||||
writer.writerow([count])
|
writer.writerow([count])
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
# type: (List[str]) -> ()
|
# type: (List[str]) -> ()
|
||||||
print("INSIDE DBUS SONICK")
|
print("INSIDE DBUS SONICK")
|
||||||
|
@ -780,11 +810,11 @@ def main(argv):
|
||||||
retry_attempts = 0
|
retry_attempts = 0
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
modbus = init_modbus(tty)
|
modbus = init_modbus(tty)
|
||||||
batteries = identify_batteries(modbus)
|
batteries = identify_batteries(modbus)
|
||||||
n = len(batteries)
|
n = len(batteries)
|
||||||
logging.info('found %d %s', n, "battery" if n == 1 else "batteries")
|
logging.info('found %d %s', n, "battery" if n == 1 else "batteries")
|
||||||
|
|
||||||
if n <= 0:
|
if n <= 0:
|
||||||
sys.exit(2) # Exit if no batteries are found
|
sys.exit(2) # Exit if no batteries are found
|
||||||
|
|
||||||
|
@ -805,7 +835,6 @@ def main(argv):
|
||||||
logging.warning('Max retry attempts reached. Continuing with fewer batteries.')
|
logging.warning('Max retry attempts reached. Continuing with fewer batteries.')
|
||||||
save_battery_counts(battery_counts)
|
save_battery_counts(battery_counts)
|
||||||
break
|
break
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
elif n == max(battery_counts):
|
elif n == max(battery_counts):
|
||||||
|
@ -825,8 +854,9 @@ def main(argv):
|
||||||
update_task() # run it right away, so that all props are initialized before anyone can ask
|
update_task() # run it right away, so that all props are initialized before anyone can ask
|
||||||
watchdog_task = create_watchdog_task(main_loop)
|
watchdog_task = create_watchdog_task(main_loop)
|
||||||
|
|
||||||
gobject.timeout_add(cfg.UPDATE_INTERVAL * 2, watchdog_task, priority = gobject.PRIORITY_LOW) # add watchdog first
|
gobject.timeout_add(cfg.UPDATE_INTERVAL * 2, watchdog_task, priority=gobject.PRIORITY_LOW) # add watchdog first
|
||||||
gobject.timeout_add(cfg.UPDATE_INTERVAL, update_task, priority = gobject.PRIORITY_LOW) # call update once every update_interval
|
gobject.timeout_add(cfg.UPDATE_INTERVAL, update_task,
|
||||||
|
priority=gobject.PRIORITY_LOW) # call update once every update_interval
|
||||||
|
|
||||||
logging.info('starting gobject.MainLoop')
|
logging.info('starting gobject.MainLoop')
|
||||||
main_loop.run()
|
main_loop.run()
|
||||||
|
@ -836,4 +866,3 @@ def main(argv):
|
||||||
|
|
||||||
|
|
||||||
main(sys.argv[1:])
|
main(sys.argv[1:])
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ async def main(remote_host):
|
||||||
|
|
||||||
##### 2. check whether it's Venus ######
|
##### 2. check whether it's Venus ######
|
||||||
gx_type = await check_GX_type(remote_host)
|
gx_type = await check_GX_type(remote_host)
|
||||||
if gx_type == "beaglebone\n":
|
# if gx_type == "beaglebone\n":
|
||||||
##### 3. upload VPN and battery files ######
|
##### 3. upload VPN and battery files ######
|
||||||
print("Upload pika and battery files!")
|
print("Upload pika and battery files!")
|
||||||
if(await upload_files(remote_host)!="All files uploaded successfully."):
|
if(await upload_files(remote_host)!="All files uploaded successfully."):
|
||||||
|
@ -172,8 +172,8 @@ async def main(remote_host):
|
||||||
##### 11. restart gui ######
|
##### 11. restart gui ######
|
||||||
print("Restart gui!")
|
print("Restart gui!")
|
||||||
print(await restart_gui(remote_host))
|
print(await restart_gui(remote_host))
|
||||||
else:
|
# else:
|
||||||
sys.exit("It's not Venus GX!")
|
# sys.exit("It's not Venus GX!")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "Inesco Energy",
|
"name": "InnovEnergy",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "Inesco Energy",
|
"name": "InnovEnergy",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "11.9.0",
|
"@emotion/react": "11.9.0",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "c",
|
"name": "InnovEnergy",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"title": "Inesco Energy",
|
"title": "InnovEnergy",
|
||||||
"private": false,
|
"private": false,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "11.9.0",
|
"@emotion/react": "11.9.0",
|
||||||
|
|
Before Width: | Height: | Size: 68 KiB |
|
@ -13,7 +13,7 @@
|
||||||
href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400&display=swap"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
<title>Inesco Energy</title>
|
<title>InnovEnergy</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
|
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 13 KiB |
|
@ -0,0 +1,88 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 28.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Ebene_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 841.89 595.28" style="enable-background:new 0 0 841.89 595.28;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#646363;}
|
||||||
|
.st1{fill:#F39200;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M114.05,430.69c2.55,1.07,6.32,1.94,10.5,1.94c6.47,0,12.13-2.7,12.13-9.69c0-7.03-4.99-9.02-11.06-11.01
|
||||||
|
c-4.79-1.53-7.55-2.91-7.55-7.04c0-3.82,2.55-5.91,7.9-5.91c2.45,0,5.15,0.61,7.54,1.38l0.76-3.11c-2.24-0.87-5.71-1.53-8.56-1.53
|
||||||
|
c-6.98,0-11.42,3.21-11.42,9.23c0,5.71,3.52,8.21,9.53,10.14c5.45,1.68,9.07,3.11,9.07,7.85c0,4.38-3.26,6.42-8.46,6.42
|
||||||
|
c-3.98,0-7.29-1.07-9.68-1.94L114.05,430.69L114.05,430.69z M165.59,418.56c0-7.54-3.98-12.85-11.98-12.85
|
||||||
|
c-2.86,0-6.42,0.71-9.64,2.39v33.34h3.57v-10.14c1.38,0.66,3.26,1.27,5.86,1.27C161.76,432.58,165.59,426.72,165.59,418.56
|
||||||
|
L165.59,418.56z M147.54,428.09V410.3c1.53-0.87,3.57-1.48,5.91-1.48c5.91,0,8.41,4.38,8.41,9.79c0,6.98-2.96,10.91-8.82,10.91
|
||||||
|
C150.6,429.52,148.92,428.81,147.54,428.09L147.54,428.09z M192.96,427.84c-2.4,1.02-5.1,1.68-7.7,1.68
|
||||||
|
c-5.81,0-9.48-3.11-9.79-9.63h18.35c0.1-0.92,0.15-1.89,0.15-3.01c0-6.22-3.62-11.16-10.4-11.16c-7.34,0-11.77,5.61-11.77,13.41
|
||||||
|
c0,8.77,5.2,13.51,13.2,13.51c3.21,0,6.12-0.61,8.61-1.78L192.96,427.84L192.96,427.84z M183.58,408.77c4.89,0,6.88,3.72,6.88,7.6
|
||||||
|
c0,0.41,0,0.61-0.05,0.97h-14.88C175.99,412.24,178.79,408.77,183.58,408.77L183.58,408.77z M205.55,406.33h-3.57v25.69h3.57
|
||||||
|
V406.33L205.55,406.33z M203.77,400.98c1.53,0,2.4-1.07,2.4-2.45c0-1.33-0.87-2.35-2.4-2.35c-1.53,0-2.4,1.02-2.4,2.35
|
||||||
|
C201.37,399.9,202.24,400.98,203.77,400.98L203.77,400.98z M225.89,405.72c-7.85,0-12.29,5.51-12.29,13.66
|
||||||
|
c0,8.41,4.64,13.25,12.9,13.25c2.55,0,5.15-0.66,6.98-1.63l-0.71-2.96c-1.89,0.92-4.03,1.48-6.12,1.48
|
||||||
|
c-6.17,0-9.38-3.57-9.38-10.19c0-6.37,3.01-10.5,8.82-10.5c2.14,0,4.43,0.56,6.37,1.32l0.76-2.9
|
||||||
|
C231.4,406.38,228.8,405.72,225.89,405.72L225.89,405.72z M244.24,432.02v-21.26c2.04-1.22,4.38-1.94,7.14-1.94
|
||||||
|
c4.54,0,6.73,2.5,6.73,6.52v16.67h3.57V415.1c0-5.81-3.57-9.38-9.94-9.38c-3.21,0-5.45,0.82-7.49,1.89v-12.49l-3.57,0.25v36.65
|
||||||
|
H244.24L244.24,432.02z M290.42,427.84c-2.4,1.02-5.1,1.68-7.7,1.68c-5.81,0-9.48-3.11-9.79-9.63h18.35
|
||||||
|
c0.1-0.92,0.15-1.89,0.15-3.01c0-6.22-3.62-11.16-10.4-11.16c-7.34,0-11.78,5.61-11.78,13.41c0,8.77,5.2,13.51,13.2,13.51
|
||||||
|
c3.21,0,6.12-0.61,8.61-1.78L290.42,427.84L290.42,427.84z M281.05,408.77c4.89,0,6.88,3.72,6.88,7.6c0,0.41,0,0.61-0.05,0.97
|
||||||
|
h-14.88C273.45,412.24,276.25,408.77,281.05,408.77L281.05,408.77z M299.45,408.32v23.7h3.57v-21.46c1.78-1.02,4.23-1.73,7.34-1.73
|
||||||
|
c0.61,0,1.48,0.05,2.14,0.25l0.51-3.11c-0.87-0.15-1.73-0.25-2.85-0.25C306.02,405.72,302.15,406.79,299.45,408.32L299.45,408.32z
|
||||||
|
M322.44,432.02v-21.46c2.19-1.17,4.69-1.73,7.24-1.73c4.59,0,6.63,2.55,6.63,6.47v16.72h3.57V415.1c0-5.81-3.31-9.38-10.2-9.38
|
||||||
|
c-3.98,0-7.7,1.02-10.81,2.6v23.7H322.44L322.44,432.02z M402.21,432.02V415.1c0-5.56-3.11-9.38-9.89-9.38
|
||||||
|
c-3.62,0-6.63,1.17-9.12,2.65c-1.63-1.68-4.03-2.65-7.29-2.65c-3.82,0-7.39,1.02-10.45,2.6v23.7h3.57v-21.46
|
||||||
|
c2.09-1.17,4.43-1.73,6.78-1.73c4.64,0,6.27,2.75,6.27,6.47v16.72h3.52v-16.46c0-1.68-0.26-3.16-0.71-4.49
|
||||||
|
c1.89-1.27,4.64-2.24,7.34-2.24c4.59,0,6.42,2.75,6.42,6.47v16.72H402.21L402.21,432.02z M415.21,406.33h-3.57v25.69h3.57V406.33
|
||||||
|
L415.21,406.33z M413.42,400.98c1.53,0,2.4-1.07,2.4-2.45c0-1.33-0.87-2.35-2.4-2.35c-1.53,0-2.4,1.02-2.4,2.35
|
||||||
|
C411.03,399.9,411.89,400.98,413.42,400.98L413.42,400.98z M436.67,432.12l-0.26-3.01c-0.87,0.25-2.09,0.41-3.11,0.41
|
||||||
|
c-2.75,0-4.38-1.27-4.38-5.05v-15.14h6.93v-3.01h-6.93v-6.32l-3.57,0.26v6.07h-3.87v3.01h3.87v15.14c0,5.96,3.01,8.16,7.49,8.16
|
||||||
|
C434.32,432.63,435.49,432.43,436.67,432.12L436.67,432.12z M457.31,430.69c2.55,1.07,6.32,1.94,10.5,1.94
|
||||||
|
c6.47,0,12.13-2.7,12.13-9.69c0-7.03-5-9.02-11.06-11.01c-4.79-1.53-7.54-2.91-7.54-7.04c0-3.82,2.55-5.91,7.9-5.91
|
||||||
|
c2.45,0,5.15,0.61,7.54,1.38l0.76-3.11c-2.24-0.87-5.71-1.53-8.56-1.53c-6.98,0-11.42,3.21-11.42,9.23c0,5.71,3.52,8.21,9.53,10.14
|
||||||
|
c5.45,1.68,9.07,3.11,9.07,7.85c0,4.38-3.26,6.42-8.46,6.42c-3.98,0-7.29-1.07-9.69-1.94L457.31,430.69L457.31,430.69z
|
||||||
|
M495.28,429.78c-3.98,0-6.37-1.58-6.37-4.79c0-3.82,2.85-5.1,6.68-5.1c2.29,0,4.13,0.36,5.81,0.71v7.75
|
||||||
|
C500.28,429.06,498.34,429.78,495.28,429.78L495.28,429.78z M504.92,430.24V415.2c0-6.12-3.31-9.48-9.94-9.48
|
||||||
|
c-2.9,0-5.96,0.61-7.95,1.48l0.82,2.96c1.89-0.81,4.38-1.32,6.88-1.32c4.64,0,6.68,2.29,6.68,6.22V418
|
||||||
|
c-1.84-0.41-4.08-0.71-6.17-0.71c-5.45,0.05-9.89,2.29-9.89,7.8c0,4.43,3.31,7.55,9.63,7.55
|
||||||
|
C499.51,432.63,502.67,431.56,504.92,430.24L504.92,430.24z M517.66,395.11l-3.57,0.25v29.41c0,5.15,2.09,7.85,6.47,7.85
|
||||||
|
c0.71,0,1.63-0.15,2.29-0.31l-0.31-2.91c-0.36,0.05-0.87,0.15-1.48,0.15c-2.6,0-3.41-1.63-3.41-4.84V395.11L517.66,395.11z
|
||||||
|
M527.4,406.33v3.01h14.53c-3.62,6.47-9.18,13.41-15.39,20.14v2.55h20.14v-3.01h-15.65c6.07-6.63,11.01-13.15,14.89-20.14v-2.55
|
||||||
|
H527.4L527.4,406.33z M558.08,396.34h-4.03v12.13c0,3.31,0.2,7.39,0.61,11.98h2.8c0.41-4.64,0.61-8.61,0.61-11.93V396.34
|
||||||
|
L558.08,396.34z M558.44,430.03c0-1.33-0.87-2.29-2.29-2.29c-1.53,0-2.4,0.97-2.4,2.29s0.87,2.35,2.4,2.35
|
||||||
|
C557.57,432.38,558.44,431.36,558.44,430.03L558.44,430.03z"/>
|
||||||
|
<path class="st0" d="M305.72,269.82v-65.28c5.44-2.72,12-4.16,18.72-4.16c12.16,0,18.08,6.72,18.08,18.4v51.04h16.16v-52.16
|
||||||
|
c0-19.52-11.84-30.88-34.24-30.88c-12.32,0-24.96,2.88-34.88,7.52v75.52H305.72L305.72,269.82z M399,269.82v-65.28
|
||||||
|
c5.44-2.72,12-4.16,18.72-4.16c12.16,0,18.08,6.72,18.08,18.4v51.04h16.16v-52.16c0-19.52-11.84-30.88-34.24-30.88
|
||||||
|
c-12.32,0-24.96,2.88-34.88,7.52v75.52H399L399,269.82z M547.32,229.18c0-25.28-14.08-42.4-38.08-42.4
|
||||||
|
c-23.68,0-37.92,17.12-37.92,42.4c0,25.44,14.24,42.56,37.92,42.56C533.24,271.74,547.32,254.62,547.32,229.18L547.32,229.18z
|
||||||
|
M487.8,229.18c0-17.44,7.36-28.8,21.44-28.8c14.56,0,21.44,11.36,21.44,28.8c0,17.6-6.88,28.96-21.44,28.96
|
||||||
|
C495.16,258.14,487.8,246.78,487.8,229.18L487.8,229.18z M575.8,188.7h-16.32c3.2,31.2,11.84,53.12,28.16,81.12h17.92
|
||||||
|
c16-28,24.32-49.92,28.16-81.12h-16.16c-2.56,27.36-9.92,47.2-20.96,67.68C585.88,235.9,578.68,216.06,575.8,188.7L575.8,188.7z"/>
|
||||||
|
<path class="st1" d="M307.68,360.51c-7.2,3.04-15.36,4.96-23.36,4.96c-15.68,0-25.44-7.84-27.04-24.96h54.56
|
||||||
|
c0.32-3.04,0.64-6.56,0.64-10.72c0-20.32-12.48-35.52-33.6-35.52c-23.36,0-38.24,17.44-38.24,42.4c0,27.04,16.8,42.56,42.24,42.56
|
||||||
|
c10.4,0,20-2.08,27.52-5.6L307.68,360.51L307.68,360.51z M278.88,307.55c12.32,0,17.92,9.28,17.92,20c0,0.96,0,1.6-0.16,2.56h-39.2
|
||||||
|
C258.88,316.35,266.4,307.55,278.88,307.55L278.88,307.55z M348.07,377.31v-65.28c5.44-2.72,12-4.16,18.72-4.16
|
||||||
|
c12.16,0,18.08,6.72,18.08,18.4v51.04h16.16v-52.16c0-19.52-11.84-30.88-34.24-30.88c-12.32,0-24.96,2.88-34.88,7.52v75.52H348.07
|
||||||
|
L348.07,377.31z M487.43,360.51c-7.2,3.04-15.36,4.96-23.36,4.96c-15.68,0-25.44-7.84-27.04-24.96h54.56
|
||||||
|
c0.32-3.04,0.64-6.56,0.64-10.72c0-20.32-12.48-35.52-33.6-35.52c-23.36,0-38.24,17.44-38.24,42.4c0,27.04,16.8,42.56,42.24,42.56
|
||||||
|
c10.4,0,20-2.08,27.52-5.6L487.43,360.51L487.43,360.51z M458.63,307.55c12.32,0,17.92,9.28,17.92,20c0,0.96,0,1.6-0.16,2.56h-39.2
|
||||||
|
C438.63,316.35,446.15,307.55,458.63,307.55L458.63,307.55z M512.71,301.95v75.36h16.16v-65.28c4.48-2.4,10.56-4.16,18.56-4.16
|
||||||
|
c2.56,0,5.6,0.32,8,1.12l2.24-13.6c-2.88-0.64-6.88-1.12-11.36-1.12C533.99,294.27,521.03,297.31,512.71,301.95L512.71,301.95z
|
||||||
|
M636.05,375.07v-74.4c-7.04-3.36-17.92-6.4-29.92-6.4c-24.8,0-41.12,15.84-41.12,41.44c0,24.32,14.4,38.24,37.28,38.24
|
||||||
|
c6.72,0,12.64-1.6,17.6-4.16v6.72c0,11.04-7.52,17.6-21.76,17.6c-8.48,0-15.36-1.28-22.4-4l-3.36,13.12
|
||||||
|
c8.16,3.2,15.2,4.64,26.72,4.64C621.81,407.87,636.05,396.35,636.05,375.07L636.05,375.07z M581.49,334.43
|
||||||
|
c0-16.48,9.44-26.56,24.64-26.56c5.12,0,10.24,1.28,13.76,2.56v45.6c-4,2.56-8.96,4.16-15.36,4.16
|
||||||
|
C589.97,360.19,581.49,350.43,581.49,334.43L581.49,334.43z M700.69,372.83c12.8-22.88,22.56-47.68,25.76-76.64h-16.16
|
||||||
|
c-2.4,27.36-8.48,45.12-18.56,65.28c-11.04-18.56-19.36-37.92-21.92-65.28h-16.32c3.36,30.72,12.64,53.44,29.76,77.76
|
||||||
|
c-6.24,10.4-16.96,16.96-27.36,19.04l2.72,13.92C674.45,403.71,688.53,394.11,700.69,372.83L700.69,372.83z"/>
|
||||||
|
<polygon class="st0" points="263.6,188.59 247.44,188.59 247.44,269.71 263.6,269.71 263.6,188.59 "/>
|
||||||
|
<path class="st1" d="M255.44,174.51c6.24,0,9.92-4,9.92-9.92c0-5.6-3.68-9.6-9.92-9.6c-6.4,0-10.08,4-10.08,9.6
|
||||||
|
C245.36,170.51,249.04,174.51,255.44,174.51L255.44,174.51z"/>
|
||||||
|
<path class="st0" d="M666.38,255.96c0,8.32-4.87,12.94-12.92,12.94c-8.12,0-12.85-4.62-12.85-12.94c0-8.25,4.73-12.94,12.85-12.94
|
||||||
|
C661.51,243.03,666.38,247.71,666.38,255.96L666.38,255.96z M637.36,255.96c0,9.51,6.29,15.78,16.1,15.78
|
||||||
|
c9.61,0,16.17-6.27,16.17-15.78s-6.49-15.78-16.17-15.78C643.72,240.19,637.36,246.46,637.36,255.96L637.36,255.96z M647.78,263.69
|
||||||
|
h3.11v-5.81h2.37c1.02,1.98,2.23,3.96,3.79,5.81h3.79c-1.83-2.18-3.31-4.23-4.4-6.27c2.23-0.73,3.25-2.38,3.25-4.62
|
||||||
|
c0-3.1-2.03-5.15-6.49-5.15h-5.41V263.69L647.78,263.69z M653.19,250.15c2.3,0,3.52,0.79,3.52,2.64c0,1.85-1.22,2.64-3.52,2.64
|
||||||
|
h-2.3v-5.28H653.19L653.19,250.15z"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 9.0 KiB |
|
@ -18,7 +18,7 @@ function Footer() {
|
||||||
>
|
>
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="subtitle1">
|
<Typography variant="subtitle1">
|
||||||
© 2024 - Inesco Energy Solutions AG
|
© 2024 - InnovEnergy AG
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Typography
|
<Typography
|
||||||
|
@ -33,7 +33,7 @@ function Footer() {
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
Inesco Energy Solutions AG
|
InnovEnergy AG
|
||||||
</Link>
|
</Link>
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -3,11 +3,14 @@ import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
|
Container,
|
||||||
|
Grid,
|
||||||
Modal,
|
Modal,
|
||||||
TextField,
|
TextField,
|
||||||
Typography,
|
Typography,
|
||||||
useTheme
|
useTheme
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
|
import innovenergyLogo from 'src/Resources/innoveng_logo_on_orange.png';
|
||||||
import { UserContext } from 'src/contexts/userContext';
|
import { UserContext } from 'src/contexts/userContext';
|
||||||
import { TokenContext } from 'src/contexts/tokenContext';
|
import { TokenContext } from 'src/contexts/tokenContext';
|
||||||
import Avatar from '@mui/material/Avatar';
|
import Avatar from '@mui/material/Avatar';
|
||||||
|
@ -15,7 +18,6 @@ import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
|
||||||
import axiosConfig from 'src/Resources/axiosConfig';
|
import axiosConfig from 'src/Resources/axiosConfig';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import routes from 'src/Resources/routes.json';
|
import routes from 'src/Resources/routes.json';
|
||||||
import inescologo from '../Resources/images/Logo.svg';
|
|
||||||
|
|
||||||
interface ForgotPasswordPromps {
|
interface ForgotPasswordPromps {
|
||||||
resetPassword: () => void;
|
resetPassword: () => void;
|
||||||
|
@ -71,6 +73,16 @@ function ForgotPassword() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Container maxWidth="xl" sx={{ pt: 2 }}>
|
||||||
|
<Grid container>
|
||||||
|
<Grid item xs={3} container justifyContent="flex-start" mb={2}>
|
||||||
|
<a href="https://monitor.innov.energy/">
|
||||||
|
<img src={innovenergyLogo} alt="innovenergy logo" height="100" />
|
||||||
|
</a>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Container>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: 8,
|
marginTop: 8,
|
||||||
|
@ -88,12 +100,7 @@ function ForgotPassword() {
|
||||||
transform: 'translate(-50%, -50%)'
|
transform: 'translate(-50%, -50%)'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'center', mb: 2 }}>
|
<Avatar sx={{ m: 1, bgcolor: '#ffc04d' }}>
|
||||||
<a href="https://monitor.innov.energy/">
|
|
||||||
<img src={inescologo} alt="inescologo" height="100" />
|
|
||||||
</a>
|
|
||||||
</Box>
|
|
||||||
<Avatar sx={{ m: 1, bgcolor: '#00b33c' }}>
|
|
||||||
<LockOutlinedIcon />
|
<LockOutlinedIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<Typography component="h1" variant="h5">
|
<Typography component="h1" variant="h5">
|
||||||
|
@ -127,15 +134,15 @@ function ForgotPassword() {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{loading && <CircularProgress sx={{ color: '#00b33c' }} />}
|
{loading && <CircularProgress sx={{ color: '#ffc04d' }} />}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
sx={{
|
sx={{
|
||||||
mt: 3,
|
mt: 3,
|
||||||
mb: 2,
|
mb: 2,
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
bgcolor: '#00b33c',
|
bgcolor: '#ffc04d',
|
||||||
'&:hover': { bgcolor: '#009933' }
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
}}
|
}}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
|
@ -174,9 +181,9 @@ function ForgotPassword() {
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: 2,
|
marginTop: 2,
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
bgcolor: '#00b33c',
|
bgcolor: '#ffc04d',
|
||||||
color: '#111111',
|
color: '#111111',
|
||||||
'&:hover': { bgcolor: '#009933' }
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
}}
|
}}
|
||||||
onClick={() => setErrorModalOpen(false)}
|
onClick={() => setErrorModalOpen(false)}
|
||||||
>
|
>
|
||||||
|
@ -214,9 +221,9 @@ function ForgotPassword() {
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: 2,
|
marginTop: 2,
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
bgcolor: '#00b33c',
|
bgcolor: '#ffc04d',
|
||||||
color: '#111111',
|
color: '#111111',
|
||||||
'&:hover': { bgcolor: '#009933' }
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
}}
|
}}
|
||||||
onClick={handleReturn}
|
onClick={handleReturn}
|
||||||
>
|
>
|
||||||
|
|
|
@ -3,18 +3,20 @@ import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
|
Container,
|
||||||
|
Grid,
|
||||||
Modal,
|
Modal,
|
||||||
TextField,
|
TextField,
|
||||||
Typography,
|
Typography,
|
||||||
useTheme
|
useTheme
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
|
import innovenergyLogo from 'src/Resources/innoveng_logo_on_orange.png';
|
||||||
import axiosConfig from 'src/Resources/axiosConfig';
|
import axiosConfig from 'src/Resources/axiosConfig';
|
||||||
import { UserContext } from 'src/contexts/userContext';
|
import { UserContext } from 'src/contexts/userContext';
|
||||||
import { TokenContext } from 'src/contexts/tokenContext';
|
import { TokenContext } from 'src/contexts/tokenContext';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import Avatar from '@mui/material/Avatar';
|
import Avatar from '@mui/material/Avatar';
|
||||||
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
|
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
|
||||||
import inescologo from '../Resources/images/Logo.svg';
|
|
||||||
|
|
||||||
function ResetPassword() {
|
function ResetPassword() {
|
||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState('');
|
||||||
|
@ -68,6 +70,16 @@ function ResetPassword() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Container maxWidth="xl" sx={{ pt: 2 }}>
|
||||||
|
<Grid container>
|
||||||
|
<Grid item xs={3} container justifyContent="flex-start" mb={2}>
|
||||||
|
<a href="https://monitor.innov.energy/">
|
||||||
|
<img src={innovenergyLogo} alt="innovenergy logo" height="100" />
|
||||||
|
</a>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Container>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: 8,
|
marginTop: 8,
|
||||||
|
@ -85,12 +97,7 @@ function ResetPassword() {
|
||||||
transform: 'translate(-50%, -50%)'
|
transform: 'translate(-50%, -50%)'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'center', mb: 2 }}>
|
<Avatar sx={{ m: 1, bgcolor: '#ffc04d' }}>
|
||||||
<a href="https://monitor.innov.energy/">
|
|
||||||
<img src={inescologo} alt="inescologo" height="100" />
|
|
||||||
</a>
|
|
||||||
</Box>
|
|
||||||
<Avatar sx={{ m: 1, bgcolor: '#00b33c' }}>
|
|
||||||
<LockOutlinedIcon />
|
<LockOutlinedIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<Typography component="h1" variant="h5">
|
<Typography component="h1" variant="h5">
|
||||||
|
@ -130,7 +137,7 @@ function ResetPassword() {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{loading && (
|
{loading && (
|
||||||
<CircularProgress sx={{ color: '#00b33c', marginLeft: '170px' }} />
|
<CircularProgress sx={{ color: '#ffc04d', marginLeft: '170px' }} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{password != verifypassword && (
|
{password != verifypassword && (
|
||||||
|
@ -148,8 +155,8 @@ function ResetPassword() {
|
||||||
mt: 3,
|
mt: 3,
|
||||||
mb: 2,
|
mb: 2,
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
bgcolor: '#00b33c',
|
bgcolor: '#ffc04d',
|
||||||
'&:hover': { bgcolor: '#009933' }
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
}}
|
}}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
|
@ -188,9 +195,9 @@ function ResetPassword() {
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: 2,
|
marginTop: 2,
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
bgcolor: '#00b33c',
|
bgcolor: '#ffc04d',
|
||||||
color: '#111111',
|
color: '#111111',
|
||||||
'&:hover': { bgcolor: '#009933' }
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
}}
|
}}
|
||||||
onClick={() => setOpen(false)}
|
onClick={() => setOpen(false)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -3,18 +3,20 @@ import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
|
Container,
|
||||||
|
Grid,
|
||||||
Modal,
|
Modal,
|
||||||
TextField,
|
TextField,
|
||||||
Typography,
|
Typography,
|
||||||
useTheme
|
useTheme
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
|
import innovenergyLogo from 'src/Resources/innoveng_logo_on_orange.png';
|
||||||
import axiosConfig from 'src/Resources/axiosConfig';
|
import axiosConfig from 'src/Resources/axiosConfig';
|
||||||
import { UserContext } from 'src/contexts/userContext';
|
import { UserContext } from 'src/contexts/userContext';
|
||||||
import { TokenContext } from 'src/contexts/tokenContext';
|
import { TokenContext } from 'src/contexts/tokenContext';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import Avatar from '@mui/material/Avatar';
|
import Avatar from '@mui/material/Avatar';
|
||||||
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
|
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
|
||||||
import inescologo from '../Resources/images/Logo.svg';
|
|
||||||
|
|
||||||
function SetNewPassword() {
|
function SetNewPassword() {
|
||||||
const [username, setUsername] = useState('');
|
const [username, setUsername] = useState('');
|
||||||
|
@ -69,6 +71,16 @@ function SetNewPassword() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<Container maxWidth="xl" sx={{ pt: 2 }}>
|
||||||
|
<Grid container>
|
||||||
|
<Grid item xs={3} container justifyContent="flex-start" mb={2}>
|
||||||
|
<a href="https://monitor.innov.energy/">
|
||||||
|
<img src={innovenergyLogo} alt="innovenergy logo" height="100" />
|
||||||
|
</a>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Container>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: 8,
|
marginTop: 8,
|
||||||
|
@ -86,12 +98,7 @@ function SetNewPassword() {
|
||||||
transform: 'translate(-50%, -50%)'
|
transform: 'translate(-50%, -50%)'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'center', mb: 2 }}>
|
<Avatar sx={{ m: 1, bgcolor: '#ffc04d' }}>
|
||||||
<a href="https://monitor.innov.energy/">
|
|
||||||
<img src={inescologo} alt="inescologo" height="100" />
|
|
||||||
</a>
|
|
||||||
</Box>
|
|
||||||
<Avatar sx={{ m: 1, bgcolor: '#00b33c' }}>
|
|
||||||
<LockOutlinedIcon />
|
<LockOutlinedIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<Typography component="h1" variant="h5">
|
<Typography component="h1" variant="h5">
|
||||||
|
@ -131,7 +138,7 @@ function SetNewPassword() {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{loading && (
|
{loading && (
|
||||||
<CircularProgress sx={{ color: '#00b33c', marginLeft: '0px' }} />
|
<CircularProgress sx={{ color: '#ffc04d', marginLeft: '0px' }} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{password != verifypassword && (
|
{password != verifypassword && (
|
||||||
|
@ -149,8 +156,8 @@ function SetNewPassword() {
|
||||||
mt: 3,
|
mt: 3,
|
||||||
mb: 2,
|
mb: 2,
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
bgcolor: '#00b33c',
|
bgcolor: '#ffc04d',
|
||||||
'&:hover': { bgcolor: '#009933' }
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
}}
|
}}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
|
@ -189,9 +196,9 @@ function SetNewPassword() {
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: 2,
|
marginTop: 2,
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
bgcolor: '#00b33c',
|
bgcolor: '#ffc04d',
|
||||||
color: '#111111',
|
color: '#111111',
|
||||||
'&:hover': { bgcolor: '#009933' }
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
}}
|
}}
|
||||||
onClick={() => setOpen(false)}
|
onClick={() => setOpen(false)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -4,6 +4,7 @@ import {
|
||||||
Button,
|
Button,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
|
Container,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
Grid,
|
Grid,
|
||||||
Modal,
|
Modal,
|
||||||
|
@ -14,7 +15,7 @@ import {
|
||||||
import Avatar from '@mui/material/Avatar';
|
import Avatar from '@mui/material/Avatar';
|
||||||
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
|
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
|
||||||
import Link from '@mui/material/Link';
|
import Link from '@mui/material/Link';
|
||||||
import inescologo from 'src/Resources/images/Logo.svg';
|
import innovenergyLogo from 'src/Resources/innoveng_logo_on_orange.png';
|
||||||
import { axiosConfigWithoutToken } from 'src/Resources/axiosConfig';
|
import { axiosConfigWithoutToken } from 'src/Resources/axiosConfig';
|
||||||
import Cookies from 'universal-cookie';
|
import Cookies from 'universal-cookie';
|
||||||
import { UserContext } from 'src/contexts/userContext';
|
import { UserContext } from 'src/contexts/userContext';
|
||||||
|
@ -101,6 +102,16 @@ function Login() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ userSelect: 'none' }}>
|
<div style={{ userSelect: 'none' }}>
|
||||||
|
<Container maxWidth="xl" sx={{ pt: 2 }} className="login">
|
||||||
|
<Grid container>
|
||||||
|
<Grid item xs={3} container justifyContent="flex-start" mb={2}>
|
||||||
|
<a href="https://monitor.innov.energy/">
|
||||||
|
<img src={innovenergyLogo} alt="innovenergy logo" height="100" />
|
||||||
|
</a>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Container>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: 8,
|
marginTop: 8,
|
||||||
|
@ -118,12 +129,7 @@ function Login() {
|
||||||
transform: 'translate(-50%, -50%)'
|
transform: 'translate(-50%, -50%)'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{ display: 'flex', justifyContent: 'center', mb: 2 }}>
|
<Avatar sx={{ m: 1, bgcolor: '#ffc04d' }}>
|
||||||
<a href="https://monitor.innov.energy/">
|
|
||||||
<img src={inescologo} alt="inescologo" height="100" />
|
|
||||||
</a>
|
|
||||||
</Box>
|
|
||||||
<Avatar sx={{ m: 1, bgcolor: '#00b33c' }}>
|
|
||||||
<LockOutlinedIcon />
|
<LockOutlinedIcon />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<Typography component="h1" variant="h5">
|
<Typography component="h1" variant="h5">
|
||||||
|
@ -179,7 +185,7 @@ function Login() {
|
||||||
checked={rememberMe}
|
checked={rememberMe}
|
||||||
onChange={handleRememberMeChange}
|
onChange={handleRememberMeChange}
|
||||||
icon={<CheckBoxOutlineBlankIcon style={{ color: 'grey' }} />}
|
icon={<CheckBoxOutlineBlankIcon style={{ color: 'grey' }} />}
|
||||||
checkedIcon={<CheckBoxIcon style={{ color: '#00b33c' }} />}
|
checkedIcon={<CheckBoxIcon style={{ color: '#ffc04d' }} />}
|
||||||
style={{ marginLeft: -175 }}
|
style={{ marginLeft: -175 }}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
@ -190,8 +196,8 @@ function Login() {
|
||||||
sx={{
|
sx={{
|
||||||
mb: 2,
|
mb: 2,
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
bgcolor: '#00b33c',
|
bgcolor: '#ffc04d',
|
||||||
'&:hover': { bgcolor: '#009933' }
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
}}
|
}}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
|
@ -204,7 +210,7 @@ function Login() {
|
||||||
{loading && (
|
{loading && (
|
||||||
<CircularProgress
|
<CircularProgress
|
||||||
sx={{
|
sx={{
|
||||||
color: '#009933',
|
color: '#ffc04d',
|
||||||
marginLeft: '20px'
|
marginLeft: '20px'
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -239,9 +245,9 @@ function Login() {
|
||||||
sx={{
|
sx={{
|
||||||
marginTop: 2,
|
marginTop: 2,
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
bgcolor: '#00b33c',
|
bgcolor: '#ffc04d',
|
||||||
color: '#111111',
|
color: '#111111',
|
||||||
'&:hover': { bgcolor: '#009933' }
|
'&:hover': { bgcolor: '#f7b34d' }
|
||||||
}}
|
}}
|
||||||
onClick={() => setOpen(false)}
|
onClick={() => setOpen(false)}
|
||||||
>
|
>
|
||||||
|
|
|
@ -390,11 +390,7 @@ function InstallationTabs() {
|
||||||
|
|
||||||
return salimaxInstallations.length > 1 ? (
|
return salimaxInstallations.length > 1 ? (
|
||||||
<>
|
<>
|
||||||
<Container
|
<Container maxWidth="xl" sx={{ marginTop: '20px' }} className="mainframe">
|
||||||
maxWidth="xl"
|
|
||||||
sx={{ marginLeft: '40px', marginTop: '20px' }}
|
|
||||||
className="mainframe"
|
|
||||||
>
|
|
||||||
<TabsContainerWrapper>
|
<TabsContainerWrapper>
|
||||||
<Tabs
|
<Tabs
|
||||||
onChange={handleTabsChange}
|
onChange={handleTabsChange}
|
||||||
|
@ -456,11 +452,7 @@ function InstallationTabs() {
|
||||||
</>
|
</>
|
||||||
) : salimaxInstallations.length === 1 ? (
|
) : salimaxInstallations.length === 1 ? (
|
||||||
<>
|
<>
|
||||||
<Container
|
<Container maxWidth="xl" sx={{ marginTop: '20px' }} className="mainframe">
|
||||||
maxWidth="xl"
|
|
||||||
sx={{ marginLeft: '40px', marginTop: '20px' }}
|
|
||||||
className="mainframe"
|
|
||||||
>
|
|
||||||
<TabsContainerWrapper>
|
<TabsContainerWrapper>
|
||||||
<Tabs
|
<Tabs
|
||||||
onChange={handleTabsChange}
|
onChange={handleTabsChange}
|
||||||
|
|
|
@ -129,7 +129,12 @@ const FlatInstallationView = (props: FlatInstallationViewProps) => {
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{sortedInstallations.map((installation) => {
|
{sortedInstallations
|
||||||
|
.filter(
|
||||||
|
(installation) =>
|
||||||
|
installation.status === -1 && installation.device === 1
|
||||||
|
)
|
||||||
|
.map((installation) => {
|
||||||
const isInstallationSelected =
|
const isInstallationSelected =
|
||||||
installation.s3BucketId === selectedInstallation;
|
installation.s3BucketId === selectedInstallation;
|
||||||
|
|
||||||
|
|
|
@ -276,11 +276,7 @@ function SalidomoInstallationTabs() {
|
||||||
|
|
||||||
return salidomoInstallations.length > 1 ? (
|
return salidomoInstallations.length > 1 ? (
|
||||||
<>
|
<>
|
||||||
<Container
|
<Container maxWidth="xl" sx={{ marginTop: '20px' }} className="mainframe">
|
||||||
maxWidth="xl"
|
|
||||||
sx={{ marginLeft: '40px', marginTop: '20px' }}
|
|
||||||
className="mainframe"
|
|
||||||
>
|
|
||||||
<TabsContainerWrapper>
|
<TabsContainerWrapper>
|
||||||
<Tabs
|
<Tabs
|
||||||
onChange={handleTabsChange}
|
onChange={handleTabsChange}
|
||||||
|
@ -346,11 +342,7 @@ function SalidomoInstallationTabs() {
|
||||||
) : salidomoInstallations.length === 1 ? (
|
) : salidomoInstallations.length === 1 ? (
|
||||||
<>
|
<>
|
||||||
{' '}
|
{' '}
|
||||||
<Container
|
<Container maxWidth="xl" sx={{ marginTop: '20px' }} className="mainframe">
|
||||||
maxWidth="xl"
|
|
||||||
sx={{ marginLeft: '40px', marginTop: '20px' }}
|
|
||||||
className="mainframe"
|
|
||||||
>
|
|
||||||
<TabsContainerWrapper>
|
<TabsContainerWrapper>
|
||||||
<Tabs
|
<Tabs
|
||||||
onChange={handleTabsChange}
|
onChange={handleTabsChange}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import Scrollbar from 'src/components/Scrollbar';
|
import Scrollbar from 'src/components/Scrollbar';
|
||||||
import { SidebarContext } from 'src/contexts/SidebarContext';
|
import { SidebarContext } from 'src/contexts/SidebarContext';
|
||||||
|
import innovenergyLogo from 'src/Resources/images/innovenergy-Logo_Speichern-mit-Salz_R_color.svg';
|
||||||
import {
|
import {
|
||||||
alpha,
|
alpha,
|
||||||
Box,
|
Box,
|
||||||
|
@ -13,11 +14,10 @@ import {
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
|
|
||||||
import SidebarMenu from './SidebarMenu';
|
import SidebarMenu from './SidebarMenu';
|
||||||
import Logo from 'src/Resources/images/Logo_for_dark_bg.svg';
|
|
||||||
|
|
||||||
const SidebarWrapper = styled(Box)(
|
const SidebarWrapper = styled(Box)(
|
||||||
({ theme }) => `
|
({ theme }) => `
|
||||||
width : 250px;
|
width: ${theme.sidebar.width};
|
||||||
min-width: ${theme.sidebar.width};
|
min-width: ${theme.sidebar.width};
|
||||||
color: ${theme.colors.alpha.trueWhite[70]};
|
color: ${theme.colors.alpha.trueWhite[70]};
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -60,11 +60,10 @@ function Sidebar() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={Logo}
|
src={innovenergyLogo}
|
||||||
alt="inesco logo"
|
alt="innovenergy logo"
|
||||||
style={{
|
style={{
|
||||||
marginLeft: '30px',
|
width: '150px' // Width of the image
|
||||||
width: '150px'
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -106,8 +105,8 @@ function Sidebar() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
src={Logo}
|
src={innovenergyLogo}
|
||||||
alt="innesco logo"
|
alt="innovenergy logo"
|
||||||
style={{
|
style={{
|
||||||
width: '150px' // Width of the image
|
width: '150px' // Width of the image
|
||||||
}}
|
}}
|
||||||
|
|