Update dbus-fzsonic skripts

This commit is contained in:
Noe 2024-12-16 15:03:27 +01:00
parent 98fb313a6f
commit 074511f6a7
35 changed files with 1097 additions and 948 deletions

View File

@ -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; } = "";

View File

@ -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();
} }

View File

@ -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

View File

@ -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)

View File

@ -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;
} }
} }

View File

@ -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);
}
}
} }

View File

@ -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();

View File

@ -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)

View File

@ -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);

Binary file not shown.

View File

@ -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

View File

@ -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:

View File

@ -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"

View File

@ -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:])

View File

@ -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__":

View File

@ -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",

View File

@ -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",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

View File

@ -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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -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

View File

@ -18,7 +18,7 @@ function Footer() {
> >
<Box> <Box>
<Typography variant="subtitle1"> <Typography variant="subtitle1">
&copy; 2024 - Inesco Energy Solutions AG &copy; 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>

View File

@ -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}
> >

View File

@ -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)}
> >

View File

@ -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)}
> >

View File

@ -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)}
> >

View File

@ -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}

View File

@ -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;

View File

@ -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}

View File

@ -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
}} }}