Merge remote-tracking branch 'origin/main'
This commit is contained in:
commit
ab051a88d1
|
|
@ -0,0 +1,90 @@
|
||||||
|
This README file provides a comprehensive guide to utilizing a Python script for interacting with S3 storage,
|
||||||
|
specifically designed for downloading and processing data files based on a specified time range and key parameters.
|
||||||
|
The script requires Python3 installed on your system and makes use of the s3cmd tool for accessing data in cloud storage.
|
||||||
|
It also illustrates the process of configuring s3cmd by creating a .s3cfg file with your access credentials. Nice
|
||||||
|
|
||||||
|
|
||||||
|
############ Create the .s3cfg file in home directory ################
|
||||||
|
|
||||||
|
nano .s3cfg
|
||||||
|
|
||||||
|
Copy this lines inside the file.
|
||||||
|
|
||||||
|
[default]
|
||||||
|
host_base = sos-ch-dk-2.exo.io
|
||||||
|
host_bucket = %(bucket)s.sos-ch-dk-2.exo.io
|
||||||
|
access_key = EXO4d838d1360ba9fb7d51648b0
|
||||||
|
secret_key = _bmrp6ewWAvNwdAQoeJuC-9y02Lsx7NV6zD-WjljzCU
|
||||||
|
use_https = True
|
||||||
|
|
||||||
|
|
||||||
|
############ S3cmd instalation ################
|
||||||
|
|
||||||
|
Please install s3cmd for retrieving data from our Cloud storage.
|
||||||
|
|
||||||
|
sudo apt install s3cmd
|
||||||
|
|
||||||
|
############ Python3 instalation ################
|
||||||
|
|
||||||
|
To check if you have already have python3, run this command
|
||||||
|
|
||||||
|
python3 --version
|
||||||
|
|
||||||
|
|
||||||
|
To install you can use this command:
|
||||||
|
|
||||||
|
1) sudo apt update
|
||||||
|
|
||||||
|
2) sudo apt install python3
|
||||||
|
|
||||||
|
3) python3 --version (to check if pyhton3 installed correctly)
|
||||||
|
|
||||||
|
|
||||||
|
############ Run extractS3data.py ################
|
||||||
|
|
||||||
|
usage: extractRange.py [-h] --key KEY --bucket-number BUCKET_NUMBER start_timestamp end_timestamp
|
||||||
|
|
||||||
|
KEY: the key can be a one word or a path
|
||||||
|
|
||||||
|
for example: /DcDc/Devices/2/Status/Dc/Battery/voltage ==> this will provide us a Dc battery Voltage of the DcDc device 2.
|
||||||
|
example : Dc/Battery/voltage ==> This will provide all DcDc Device voltage (including the avg voltage of all DcDc device)
|
||||||
|
example : voltage ==> This will provide all voltage of all devices in the Salimax
|
||||||
|
|
||||||
|
BUCKET_NUMBER: This a number of bucket name for the instalation
|
||||||
|
|
||||||
|
start_timestamp end_timestamp: this must be a correct timestamp of 10 digits.
|
||||||
|
The start_timestamp must be smaller than the end_timestamp.
|
||||||
|
|
||||||
|
PS: The data will be downloaded to a folder named S3cmdData_{Bucket_Number}. If this folder does not exist, it will be created.
|
||||||
|
If the folder exist, it will try to download data between the requested timestamps if they files are not already existing.
|
||||||
|
|
||||||
|
Example command:
|
||||||
|
|
||||||
|
python3 extractS3data.py 1749062721 1749106001 --keys GridMeter/Ac/Power/Active --bucket-number 12 --product_name=SodistoreMax
|
||||||
|
|
||||||
|
|
||||||
|
################################ EXTENDED FEATURES FOR MORE ADVANCED USAGE ################################
|
||||||
|
|
||||||
|
1) Multiple Keys Support:
|
||||||
|
|
||||||
|
The script supports the extraction of data using multiple keys. Users can specify one or multiple keys separated by commas with the --keys parameter.
|
||||||
|
This feature allows for more granular data extraction, catering to diverse data analysis requirements. For example, users can extract data for different
|
||||||
|
metrics or parameters from the same or different CSV files within the specified range.
|
||||||
|
|
||||||
|
3) Dynamic Header Generation:
|
||||||
|
|
||||||
|
The script dynamically generates headers for the output CSV file based on the keys provided. This ensures that the output file accurately reflects the
|
||||||
|
extracted data, providing a clear and understandable format for subsequent analysis. The headers correspond to the keys used for data extraction, making
|
||||||
|
it easy to identify and analyze the extracted data.
|
||||||
|
|
||||||
|
4)Advanced Data Processing Capabilities:
|
||||||
|
|
||||||
|
Booleans as Numbers: The --booleans_as_numbers flag allows users to convert boolean values (True/False) into numeric representations (1/0). This feature
|
||||||
|
is particularly useful for analytical tasks that require numerical data processing.
|
||||||
|
|
||||||
|
Example Command:
|
||||||
|
|
||||||
|
python3 extractS3data.py 1749062721 1749106001 --keys AcDc/SystemControl/ResetAlarmsAndWarnings,AcDc/Devices/1/Status/Ac/L1/Voltage --bucket-number 12 --product_name=SodistoreMax
|
||||||
|
|
||||||
|
This command extracts data for AcDc/SystemControl/ResetAlarmsAndWarnings and AcDc/Devices/1/Status/Ac/L1/Voltage keys from bucket number 12, between the specified timestamps, with boolean values converted to numbers.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,937 @@
|
||||||
|
{
|
||||||
|
"AcDc": {
|
||||||
|
"SystemControl": {
|
||||||
|
"Alarms": "",
|
||||||
|
"CommunicationTimeout": "00:00:20",
|
||||||
|
"SystemConfig": "AcDcAndDcDc",
|
||||||
|
"ResetAlarmsAndWarnings": "True",
|
||||||
|
"TargetSlave": 0.0,
|
||||||
|
"UseSlaveIdForAddressing": "True",
|
||||||
|
"ReferenceFrame": "Consumer",
|
||||||
|
"SlaveErrorHandling": "Relaxed",
|
||||||
|
"SubSlaveErrorHandling": "Off",
|
||||||
|
"PowerSetPointActivation": "Immediate",
|
||||||
|
"PowerSetPointTrigger": "Wait",
|
||||||
|
"DeviceState": "Operation",
|
||||||
|
"NumberOfConnectedSlaves": 2.0,
|
||||||
|
"NumberOfConnectedSubSlaves": 0.0,
|
||||||
|
"Warnings": ""
|
||||||
|
},
|
||||||
|
"Devices": {
|
||||||
|
"1": {
|
||||||
|
"Status": {
|
||||||
|
"Ac": {
|
||||||
|
"L1": {
|
||||||
|
"Voltage": 238.8,
|
||||||
|
"Current": 1.45,
|
||||||
|
"Phi": 3.09,
|
||||||
|
"Power": {
|
||||||
|
"Active": -345.73,
|
||||||
|
"Reactive": 19.21,
|
||||||
|
"Apparent": 346.26
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"L2": {
|
||||||
|
"Voltage": 239.2,
|
||||||
|
"Current": 1.53,
|
||||||
|
"Phi": -3.09,
|
||||||
|
"Power": {
|
||||||
|
"Active": -365.41,
|
||||||
|
"Reactive": -20.3,
|
||||||
|
"Apparent": 365.98
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"L3": {
|
||||||
|
"Voltage": 239.9,
|
||||||
|
"Current": 1.31,
|
||||||
|
"Phi": 3.14,
|
||||||
|
"Power": {
|
||||||
|
"Active": -314.26,
|
||||||
|
"Reactive": 1.97,
|
||||||
|
"Apparent": 314.27
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Frequency": 50.0,
|
||||||
|
"Power": {
|
||||||
|
"Active": -1025.4,
|
||||||
|
"Reactive": 0.88,
|
||||||
|
"Apparent": 1025.4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PowerLimitedBy": "DcLink",
|
||||||
|
"InverterState": {
|
||||||
|
"Current": "AcConnected",
|
||||||
|
"OnLastAlarm": "Alarm"
|
||||||
|
},
|
||||||
|
"ActiveGridType": "GridTied400V50Hz",
|
||||||
|
"DcVoltages": {
|
||||||
|
"Intern": {
|
||||||
|
"DcUpperHalf": 389.0,
|
||||||
|
"DcLowerHalf": 390.0,
|
||||||
|
"NToPe": 6553.5
|
||||||
|
},
|
||||||
|
"Extern": {
|
||||||
|
"UpperHalf": 389.0,
|
||||||
|
"LowerHalf": 390.0,
|
||||||
|
"NToPe": 0.7
|
||||||
|
},
|
||||||
|
"Active": {
|
||||||
|
"ActiveUpperVoltage": 780.0,
|
||||||
|
"ActiveLowerVoltage": 720.0,
|
||||||
|
"ActiveRefVoltage": 750.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Temperature": {
|
||||||
|
"InletAir": 23.9,
|
||||||
|
"IgbtL1": 49.7,
|
||||||
|
"IgbtL2": 47.6,
|
||||||
|
"IgbtL3": 51.8,
|
||||||
|
"IgbtBalancer": 50.6
|
||||||
|
},
|
||||||
|
"OverloadCapacity": {
|
||||||
|
"L1": 100.0,
|
||||||
|
"L2": 100.0,
|
||||||
|
"L3": 100.0
|
||||||
|
},
|
||||||
|
"Nominal": {
|
||||||
|
"AcFrequency": 50.0,
|
||||||
|
"AcVoltage": 400.0,
|
||||||
|
"Power": 25000.0
|
||||||
|
},
|
||||||
|
"Alarms": "",
|
||||||
|
"Warnings": ""
|
||||||
|
},
|
||||||
|
"Control": {
|
||||||
|
"Ac": {
|
||||||
|
"Power": {
|
||||||
|
"L1": {
|
||||||
|
"Active": 3.81,
|
||||||
|
"Reactive": 0.0,
|
||||||
|
"Apparent": 3.81
|
||||||
|
},
|
||||||
|
"L2": {
|
||||||
|
"Active": 3.81,
|
||||||
|
"Reactive": 0.0,
|
||||||
|
"Apparent": 3.81
|
||||||
|
},
|
||||||
|
"L3": {
|
||||||
|
"Active": 3.81,
|
||||||
|
"Reactive": 0.0,
|
||||||
|
"Apparent": 3.81
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PhaseControl": "Asymmetric",
|
||||||
|
"GridType": "GridTied400V50Hz",
|
||||||
|
"IslandMode": {
|
||||||
|
"FrequencyOffset": 0.0,
|
||||||
|
"VoltageAdjustmentFactor": 100.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Dc": {
|
||||||
|
"ReferenceVoltage": 750.0,
|
||||||
|
"MinVoltage": 720.0,
|
||||||
|
"MaxVoltage": 780.0,
|
||||||
|
"PrechargeConfig": "PrechargeDcWithInternal"
|
||||||
|
},
|
||||||
|
"PowerStageEnable": "True",
|
||||||
|
"ResetAlarmsAndWarnings": "False"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"Status": {
|
||||||
|
"Ac": {
|
||||||
|
"L1": {
|
||||||
|
"Voltage": 239.0,
|
||||||
|
"Current": 0.74,
|
||||||
|
"Phi": -0.1,
|
||||||
|
"Power": {
|
||||||
|
"Active": 175.89,
|
||||||
|
"Reactive": -18.51,
|
||||||
|
"Apparent": 176.86
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"L2": {
|
||||||
|
"Voltage": 239.5,
|
||||||
|
"Current": 0.62,
|
||||||
|
"Phi": -0.77,
|
||||||
|
"Power": {
|
||||||
|
"Active": 106.89,
|
||||||
|
"Reactive": -103.07,
|
||||||
|
"Apparent": 148.49
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"L3": {
|
||||||
|
"Voltage": 239.8,
|
||||||
|
"Current": 0.47,
|
||||||
|
"Phi": -0.07,
|
||||||
|
"Power": {
|
||||||
|
"Active": 112.42,
|
||||||
|
"Reactive": -8.03,
|
||||||
|
"Apparent": 112.71
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Frequency": 50.01,
|
||||||
|
"Power": {
|
||||||
|
"Active": 395.2,
|
||||||
|
"Reactive": -129.62,
|
||||||
|
"Apparent": 415.91
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PowerLimitedBy": "Nothing",
|
||||||
|
"InverterState": {
|
||||||
|
"Current": "AcConnected",
|
||||||
|
"OnLastAlarm": "Idle"
|
||||||
|
},
|
||||||
|
"ActiveGridType": "GridTied400V50Hz",
|
||||||
|
"DcVoltages": {
|
||||||
|
"Intern": {
|
||||||
|
"DcUpperHalf": 388.0,
|
||||||
|
"DcLowerHalf": 389.0,
|
||||||
|
"NToPe": 0.1
|
||||||
|
},
|
||||||
|
"Extern": {
|
||||||
|
"UpperHalf": 388.0,
|
||||||
|
"LowerHalf": 388.0,
|
||||||
|
"NToPe": 6553.4
|
||||||
|
},
|
||||||
|
"Active": {
|
||||||
|
"ActiveUpperVoltage": 780.0,
|
||||||
|
"ActiveLowerVoltage": 720.0,
|
||||||
|
"ActiveRefVoltage": 750.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Temperature": {
|
||||||
|
"InletAir": 26.0,
|
||||||
|
"IgbtL1": 49.0,
|
||||||
|
"IgbtL2": 47.0,
|
||||||
|
"IgbtL3": 50.0,
|
||||||
|
"IgbtBalancer": 48.0
|
||||||
|
},
|
||||||
|
"OverloadCapacity": {
|
||||||
|
"L1": 100.0,
|
||||||
|
"L2": 100.0,
|
||||||
|
"L3": 100.0
|
||||||
|
},
|
||||||
|
"Nominal": {
|
||||||
|
"AcFrequency": 50.0,
|
||||||
|
"AcVoltage": 400.0,
|
||||||
|
"Power": 25000.0
|
||||||
|
},
|
||||||
|
"Alarms": "",
|
||||||
|
"Warnings": ""
|
||||||
|
},
|
||||||
|
"Control": {
|
||||||
|
"Ac": {
|
||||||
|
"Power": {
|
||||||
|
"L1": {
|
||||||
|
"Active": 3.81,
|
||||||
|
"Reactive": 0.0,
|
||||||
|
"Apparent": 3.81
|
||||||
|
},
|
||||||
|
"L2": {
|
||||||
|
"Active": 3.81,
|
||||||
|
"Reactive": 0.0,
|
||||||
|
"Apparent": 3.81
|
||||||
|
},
|
||||||
|
"L3": {
|
||||||
|
"Active": 3.81,
|
||||||
|
"Reactive": 0.0,
|
||||||
|
"Apparent": 3.81
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PhaseControl": "Asymmetric",
|
||||||
|
"GridType": "GridTied400V50Hz",
|
||||||
|
"IslandMode": {
|
||||||
|
"FrequencyOffset": 0.0,
|
||||||
|
"VoltageAdjustmentFactor": 100.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Dc": {
|
||||||
|
"ReferenceVoltage": 750.0,
|
||||||
|
"MinVoltage": 720.0,
|
||||||
|
"MaxVoltage": 780.0,
|
||||||
|
"PrechargeConfig": "PrechargeDcWithInternal"
|
||||||
|
},
|
||||||
|
"PowerStageEnable": "True",
|
||||||
|
"ResetAlarmsAndWarnings": "False"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Alarms": "",
|
||||||
|
"Warnings": "",
|
||||||
|
"Ac": {
|
||||||
|
"L1": {
|
||||||
|
"Voltage": 238.9,
|
||||||
|
"Current": 2.19,
|
||||||
|
"Phi": 3.14,
|
||||||
|
"Power": {
|
||||||
|
"Active": -523.19,
|
||||||
|
"Reactive": 2.13,
|
||||||
|
"Apparent": 523.19
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"L2": {
|
||||||
|
"Voltage": 239.35,
|
||||||
|
"Current": 2.15,
|
||||||
|
"Phi": -2.7,
|
||||||
|
"Power": {
|
||||||
|
"Active": -464.43,
|
||||||
|
"Reactive": -221.64,
|
||||||
|
"Apparent": 514.6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"L3": {
|
||||||
|
"Voltage": 239.85,
|
||||||
|
"Current": 1.78,
|
||||||
|
"Phi": -3.11,
|
||||||
|
"Power": {
|
||||||
|
"Active": -426.74,
|
||||||
|
"Reactive": -12.81,
|
||||||
|
"Apparent": 426.93
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Frequency": 50.0,
|
||||||
|
"Power": {
|
||||||
|
"Active": -1414.36,
|
||||||
|
"Reactive": -232.31,
|
||||||
|
"Apparent": 1433.31
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Dc": {
|
||||||
|
"Voltage": 777.5,
|
||||||
|
"Current": -1.82,
|
||||||
|
"Power": -1414.36
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DcDc": {
|
||||||
|
"Dc": {
|
||||||
|
"Link": {
|
||||||
|
"Voltage": 775.5,
|
||||||
|
"Current": 0.0,
|
||||||
|
"Power": 0.0
|
||||||
|
},
|
||||||
|
"Battery": {
|
||||||
|
"Voltage": 61.2,
|
||||||
|
"Current": 0.0,
|
||||||
|
"Power": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SystemControl": {
|
||||||
|
"Alarms": "",
|
||||||
|
"CommunicationTimeout": "00:00:20",
|
||||||
|
"SystemConfig": "DcDcOnly",
|
||||||
|
"ResetAlarmsAndWarnings": "True",
|
||||||
|
"TargetSlave": 2.0,
|
||||||
|
"UseSlaveIdForAddressing": "True",
|
||||||
|
"ReferenceFrame": "Producer",
|
||||||
|
"SlaveErrorHandling": "Relaxed",
|
||||||
|
"SubSlaveErrorHandling": "Off",
|
||||||
|
"PowerSetPointActivation": "Immediate",
|
||||||
|
"PowerSetPointTrigger": "Wait",
|
||||||
|
"DeviceState": "Operation",
|
||||||
|
"NumberOfConnectedSlaves": 2.0,
|
||||||
|
"NumberOfConnectedSubSlaves": 0.0,
|
||||||
|
"Warnings": ""
|
||||||
|
},
|
||||||
|
"Devices": {
|
||||||
|
"1": {
|
||||||
|
"Status": {
|
||||||
|
"Dc": {
|
||||||
|
"Link": {
|
||||||
|
"Voltage": 775.0,
|
||||||
|
"Current": -0.0,
|
||||||
|
"Power": -0.0
|
||||||
|
},
|
||||||
|
"Battery": {
|
||||||
|
"Voltage": 61.2,
|
||||||
|
"Current": -0.0,
|
||||||
|
"Power": -0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"OverloadCapacity": 0.0,
|
||||||
|
"Temperature": {
|
||||||
|
"InletAir": 25.0,
|
||||||
|
"HighVoltageModule": 30.0,
|
||||||
|
"LowVoltageModule": 28.0
|
||||||
|
},
|
||||||
|
"PowerLimitedBy": "MaxChargeCurrent",
|
||||||
|
"Alarms": "",
|
||||||
|
"Warnings": ""
|
||||||
|
},
|
||||||
|
"Control": {
|
||||||
|
"Vcc": {
|
||||||
|
"EndPointCurrent": 50.0,
|
||||||
|
"EndPointVoltage": 50.0,
|
||||||
|
"StartPointCurrent": 5.0
|
||||||
|
},
|
||||||
|
"VoltageLimits": {
|
||||||
|
"MinBatteryVoltageAlarm": 0.0,
|
||||||
|
"MaxBatteryVoltageAlarm": 64.0,
|
||||||
|
"MinBatteryVoltage": 32.0,
|
||||||
|
"MaxBatteryVoltage": 63.0
|
||||||
|
},
|
||||||
|
"DroopControl": {
|
||||||
|
"ReferenceVoltage": 750.0,
|
||||||
|
"LowerVoltage": 20.0,
|
||||||
|
"UpperVoltage": 20.0,
|
||||||
|
"VoltageDeadband": 0.0
|
||||||
|
},
|
||||||
|
"CurrentControl": {
|
||||||
|
"CurrentSetpoint": 0.0,
|
||||||
|
"MaxCurrentChangePerMs": 100.0,
|
||||||
|
"MaxBatteryChargingCurrent": 0.0,
|
||||||
|
"MaxBatteryDischargingCurrent": 210.0
|
||||||
|
},
|
||||||
|
"MaxDcPower": 10000.0,
|
||||||
|
"ControlMode": "VoltageDroop",
|
||||||
|
"ResetAlarmsAndWarnings": "False",
|
||||||
|
"PowerStageEnable": "True"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"Status": {
|
||||||
|
"Dc": {
|
||||||
|
"Link": {
|
||||||
|
"Voltage": 776.0,
|
||||||
|
"Current": -0.0,
|
||||||
|
"Power": -0.0
|
||||||
|
},
|
||||||
|
"Battery": {
|
||||||
|
"Voltage": 61.2,
|
||||||
|
"Current": -0.0,
|
||||||
|
"Power": -0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"OverloadCapacity": 0.0,
|
||||||
|
"Temperature": {
|
||||||
|
"InletAir": 23.0,
|
||||||
|
"HighVoltageModule": 30.0,
|
||||||
|
"LowVoltageModule": 29.0
|
||||||
|
},
|
||||||
|
"PowerLimitedBy": "MaxChargeCurrent",
|
||||||
|
"Alarms": "",
|
||||||
|
"Warnings": ""
|
||||||
|
},
|
||||||
|
"Control": {
|
||||||
|
"Vcc": {
|
||||||
|
"EndPointCurrent": 50.0,
|
||||||
|
"EndPointVoltage": 50.0,
|
||||||
|
"StartPointCurrent": 5.0
|
||||||
|
},
|
||||||
|
"VoltageLimits": {
|
||||||
|
"MinBatteryVoltageAlarm": 0.0,
|
||||||
|
"MaxBatteryVoltageAlarm": 64.0,
|
||||||
|
"MinBatteryVoltage": 32.0,
|
||||||
|
"MaxBatteryVoltage": 63.0
|
||||||
|
},
|
||||||
|
"DroopControl": {
|
||||||
|
"ReferenceVoltage": 750.0,
|
||||||
|
"LowerVoltage": 20.0,
|
||||||
|
"UpperVoltage": 20.0,
|
||||||
|
"VoltageDeadband": 0.0
|
||||||
|
},
|
||||||
|
"CurrentControl": {
|
||||||
|
"CurrentSetpoint": 0.0,
|
||||||
|
"MaxCurrentChangePerMs": 100.0,
|
||||||
|
"MaxBatteryChargingCurrent": 0.0,
|
||||||
|
"MaxBatteryDischargingCurrent": 210.0
|
||||||
|
},
|
||||||
|
"MaxDcPower": 10000.0,
|
||||||
|
"ControlMode": "VoltageDroop",
|
||||||
|
"ResetAlarmsAndWarnings": "False",
|
||||||
|
"PowerStageEnable": "True"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Alarms": "",
|
||||||
|
"Warnings": ""
|
||||||
|
},
|
||||||
|
"Battery": {
|
||||||
|
"Current": -1.25,
|
||||||
|
"Voltage": 61.31,
|
||||||
|
"Soc": 99.85,
|
||||||
|
"Soh": 100.0,
|
||||||
|
"CurrentMinSoc": 99.3,
|
||||||
|
"TemperatureCell1": 23.35,
|
||||||
|
"Power": -76.62,
|
||||||
|
"LowestCellVoltage": 3.51,
|
||||||
|
"HighestCellVoltage": 3.89,
|
||||||
|
"MonomerHighVoltageAlarm": "True",
|
||||||
|
"MonomerLowVoltageAlarm": "False",
|
||||||
|
"ChargeSwitchState": "False",
|
||||||
|
"DischargeSwitchState": "True",
|
||||||
|
"AvailableDischBatteries": 6.0,
|
||||||
|
"AvailableChBatteries": 0.0,
|
||||||
|
"ChargeModeBatteries": 0.0,
|
||||||
|
"DischargeModeBatteries": 1.0,
|
||||||
|
"StandbyModeBatteries": 5.0,
|
||||||
|
"ShutDownModeBatteries": 0.0,
|
||||||
|
"Eoc": "False",
|
||||||
|
"Eod": "False",
|
||||||
|
"Devices": {
|
||||||
|
"1": {
|
||||||
|
"BatteryDeligreenDataRecord": {
|
||||||
|
"FwVersion": 2.0,
|
||||||
|
"BusVoltage": 61.33,
|
||||||
|
"BusCurrent": 0.0,
|
||||||
|
"Power": 0.0,
|
||||||
|
"TotalBatteryVoltage": 58.66,
|
||||||
|
"ResidualCapacity": 209.99,
|
||||||
|
"BatteryCapacity": 210.0,
|
||||||
|
"Soc": 99.9,
|
||||||
|
"RatedCapacity": 210.0,
|
||||||
|
"NumberOfCycles": 58.0,
|
||||||
|
"Soh": 100.0,
|
||||||
|
"CellVoltage": "3.742,3.564,3.887,3.644,3.599,3.574,3.601,3.555,3.528,3.58,3.823,3.753,3.693,3.771,3.569,3.778",
|
||||||
|
"TemperaturesList": {
|
||||||
|
"CellTemperature1": 22.2,
|
||||||
|
"CellTemperature2": 21.5,
|
||||||
|
"CellTemperature3": 21.5,
|
||||||
|
"CellTemperature4": 21.2,
|
||||||
|
"EnvironmentTemperature": 28.1,
|
||||||
|
"PowerTemperature": 23.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"BatteryDeligreenAlarmRecord": {
|
||||||
|
"CellAlarmList": "Normal-no alarm,Normal-no alarm,Alarm that analog quantity reaches the upper limit,Normal-no alarm,Normal-no alarm,Normal-no alarm,Normal-no alarm,Normal-no alarm,Normal-no alarm,Normal-no alarm,Alarm that analog quantity reaches the upper limit,Normal-no alarm,Normal-no alarm,Alarm that analog quantity reaches the upper limit,Normal-no alarm,Alarm that analog quantity reaches the upper limit",
|
||||||
|
"CellTemperatureAlarm": "Normal-no alarm,Normal-no alarm,Normal-no alarm,Normal-no alarm",
|
||||||
|
"EnviTempAlarm": "Normal-no alarm",
|
||||||
|
"PowerTempAlarm": "Normal-no alarm",
|
||||||
|
"CurrentAlarm": "Normal-no alarm",
|
||||||
|
"TotalVoltageAlarm": "Normal-no alarm",
|
||||||
|
"AlarmEvent1": {
|
||||||
|
"VoltageSensorFault": "False",
|
||||||
|
"TemperatureSensorFault": "False",
|
||||||
|
"CurrentSensorFault": "False",
|
||||||
|
"KeySwitchFault": "False",
|
||||||
|
"CellVoltageDropoutFault": "False",
|
||||||
|
"ChargeSwitchFault": "False",
|
||||||
|
"DischargeSwitchFault": "False",
|
||||||
|
"CurrentLimitSwitchFault": "False"
|
||||||
|
},
|
||||||
|
"AlarmEvent2": {
|
||||||
|
"MonomerHighVoltageAlarm": "False",
|
||||||
|
"MonomerOvervoltageProtection": "True",
|
||||||
|
"MonomerLowVoltageAlarm": "False",
|
||||||
|
"MonomerUnderVoltageProtection": "False",
|
||||||
|
"HighVoltageAlarmForTotalVoltage": "False",
|
||||||
|
"OvervoltageProtectionForTotalVoltage": "False",
|
||||||
|
"LowVoltageAlarmForTotalVoltage": "False",
|
||||||
|
"UnderVoltageProtectionForTotalVoltage": "False"
|
||||||
|
},
|
||||||
|
"AlarmEvent3": {
|
||||||
|
"ChargeHighTemperatureAlarm": "False",
|
||||||
|
"ChargeOverTemperatureProtection": "False",
|
||||||
|
"ChargeLowTemperatureAlarm": "False",
|
||||||
|
"ChargeUnderTemperatureProtection": "False",
|
||||||
|
"DischargeHighTemperatureAlarm": "False",
|
||||||
|
"DischargeOverTemperatureProtection": "False",
|
||||||
|
"DischargeLowTemperatureAlarm": "False",
|
||||||
|
"DischargeUnderTemperatureProtection": "False"
|
||||||
|
},
|
||||||
|
"AlarmEvent4": {
|
||||||
|
"EnvironmentHighTemperatureAlarm": "False",
|
||||||
|
"EnvironmentOverTemperatureProtection": "False",
|
||||||
|
"EnvironmentLowTemperatureAlarm": "False",
|
||||||
|
"EnvironmentUnderTemperatureProtection": "False",
|
||||||
|
"PowerOverTemperatureProtection": "False",
|
||||||
|
"PowerHighTemperatureAlarm": "False",
|
||||||
|
"CellLowTemperatureHeating": "False",
|
||||||
|
"ReservationBit": "False"
|
||||||
|
},
|
||||||
|
"AlarmEvent5": {
|
||||||
|
"ChargeOverCurrentAlarm": "False",
|
||||||
|
"ChargeOverCurrentProtection": "False",
|
||||||
|
"DischargeOverCurrentAlarm": "False",
|
||||||
|
"DischargeOverCurrentProtection": "False",
|
||||||
|
"TransientOverCurrentProtection": "False",
|
||||||
|
"OutputShortCircuitProtection": "False",
|
||||||
|
"TransientOverCurrentLockout": "False",
|
||||||
|
"OutputShortCircuitLockout": "False"
|
||||||
|
},
|
||||||
|
"AlarmEvent6": {
|
||||||
|
"ChargeHighVoltageProtection": "False",
|
||||||
|
"IntermittentRechargeWaiting": "True",
|
||||||
|
"ResidualCapacityAlarm": "False",
|
||||||
|
"ResidualCapacityProtection": "False",
|
||||||
|
"CellLowVoltageChargingProhibition": "False",
|
||||||
|
"OutputReversePolarityProtection": "False",
|
||||||
|
"OutputConnectionFault": "False",
|
||||||
|
"InsideBit": "False"
|
||||||
|
},
|
||||||
|
"AlarmEvent7": {
|
||||||
|
"InsideBit1": "False",
|
||||||
|
"InsideBit2": "False",
|
||||||
|
"InsideBit3": "False",
|
||||||
|
"InsideBit4": "False",
|
||||||
|
"AutomaticChargingWaiting": "False",
|
||||||
|
"ManualChargingWaiting": "False",
|
||||||
|
"InsideBit5": "False",
|
||||||
|
"InsideBit6": "False"
|
||||||
|
},
|
||||||
|
"AlarmEvent8": {
|
||||||
|
"EepStorageFault": "False",
|
||||||
|
"RtcError": "False",
|
||||||
|
"VoltageCalibrationNotPerformed": "False",
|
||||||
|
"CurrentCalibrationNotPerformed": "False",
|
||||||
|
"ZeroCalibrationNotPerformed": "False",
|
||||||
|
"InsideBit1": "False",
|
||||||
|
"InsideBit2": "False",
|
||||||
|
"InsideBit3": "False"
|
||||||
|
},
|
||||||
|
"DisconnectionState1": {
|
||||||
|
"Cell01Disconnection": "False",
|
||||||
|
"Cell02Disconnection": "False",
|
||||||
|
"Cell03Disconnection": "False",
|
||||||
|
"Cell04Disconnection": "False",
|
||||||
|
"Cell05Disconnection": "False",
|
||||||
|
"Cell06Disconnection": "False",
|
||||||
|
"Cell07Disconnection": "False",
|
||||||
|
"Cell08Disconnection": "False"
|
||||||
|
},
|
||||||
|
"DisconnectionState2": {
|
||||||
|
"Cell09Disconnection": "False",
|
||||||
|
"Cell10Disconnection": "False",
|
||||||
|
"Cell11Disconnection": "False",
|
||||||
|
"Cell12Disconnection": "False",
|
||||||
|
"Cell13Disconnection": "False",
|
||||||
|
"Cell14Disconnection": "False",
|
||||||
|
"Cell15Disconnection": "False",
|
||||||
|
"Cell16Disconnection": "False"
|
||||||
|
},
|
||||||
|
"EquilibriumState1": {
|
||||||
|
"Cell01Equilibrium": "False",
|
||||||
|
"Cell02Equilibrium": "False",
|
||||||
|
"Cell03Equilibrium": "False",
|
||||||
|
"Cell04Equilibrium": "False",
|
||||||
|
"Cell05Equilibrium": "False",
|
||||||
|
"Cell06Equilibrium": "False",
|
||||||
|
"Cell07Equilibrium": "False",
|
||||||
|
"Cell08Equilibrium": "False"
|
||||||
|
},
|
||||||
|
"EquilibriumState2": {
|
||||||
|
"Cell09Equilibrium": "False",
|
||||||
|
"Cell10Equilibrium": "False",
|
||||||
|
"Cell11Equilibrium": "False",
|
||||||
|
"Cell12Equilibrium": "False",
|
||||||
|
"Cell13Equilibrium": "False",
|
||||||
|
"Cell14Equilibrium": "False",
|
||||||
|
"Cell15Equilibrium": "False",
|
||||||
|
"Cell16Equilibrium": "False"
|
||||||
|
},
|
||||||
|
"OnOffState": {
|
||||||
|
"DischargeSwitchState": "True",
|
||||||
|
"ChargeSwitchState": "False",
|
||||||
|
"CurrentLimitSwitchStat": "False",
|
||||||
|
"HeatingSwitchState": "False",
|
||||||
|
"ReservationBit1": "False",
|
||||||
|
"ReservationBit2": "False",
|
||||||
|
"ReservationBit3": "False",
|
||||||
|
"ReservationBit4": "False"
|
||||||
|
},
|
||||||
|
"SystemState": {
|
||||||
|
"Discharge": "False",
|
||||||
|
"Charge": "False",
|
||||||
|
"FloatingCharge": "False",
|
||||||
|
"ReservationBit1": "False",
|
||||||
|
"Standby": "True",
|
||||||
|
"Shutdown": "False",
|
||||||
|
"ReservationBit2": "False",
|
||||||
|
"ReservationBit3": "False"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"2" :{...}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"GridMeter": {
|
||||||
|
"Ac": {
|
||||||
|
"L1": {
|
||||||
|
"Voltage": 239.0,
|
||||||
|
"Current": 0.36,
|
||||||
|
"Phi": -1.55,
|
||||||
|
"Power": {
|
||||||
|
"Active": 1.99,
|
||||||
|
"Reactive": -86.59,
|
||||||
|
"Apparent": 86.61
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"L2": {
|
||||||
|
"Voltage": 239.3,
|
||||||
|
"Current": 0.32,
|
||||||
|
"Phi": -1.66,
|
||||||
|
"Power": {
|
||||||
|
"Active": -7.02,
|
||||||
|
"Reactive": -77.2,
|
||||||
|
"Apparent": 77.52
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"L3": {
|
||||||
|
"Voltage": 239.5,
|
||||||
|
"Current": 1.14,
|
||||||
|
"Phi": -1.96,
|
||||||
|
"Power": {
|
||||||
|
"Active": -103.28,
|
||||||
|
"Reactive": -252.68,
|
||||||
|
"Apparent": 272.97
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Frequency": 50.0,
|
||||||
|
"Power": {
|
||||||
|
"Active": -108.3,
|
||||||
|
"Reactive": -416.47,
|
||||||
|
"Apparent": 430.32
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ActivePowerImportT1": 28349.0,
|
||||||
|
"ActivePowerExportT1": 61296.0,
|
||||||
|
"ActivePowerImportT2": 28349.0,
|
||||||
|
"ActivePowerExportT2": 61296.0,
|
||||||
|
"ActivePowerImportT3": 46886.0,
|
||||||
|
"ActivePowerExportT3": 21032.0,
|
||||||
|
"ActivePowerImportT4": 0.0,
|
||||||
|
"ActivePowerExportT4": 0.0
|
||||||
|
},
|
||||||
|
"LoadOnAcIsland": {
|
||||||
|
"Ac": {
|
||||||
|
"L1": {
|
||||||
|
"Voltage": 239.0,
|
||||||
|
"Current": 0.0,
|
||||||
|
"Phi": 0.0,
|
||||||
|
"Power": {
|
||||||
|
"Active": 0.0,
|
||||||
|
"Reactive": 0.0,
|
||||||
|
"Apparent": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"L2": {
|
||||||
|
"Voltage": 239.3,
|
||||||
|
"Current": 0.0,
|
||||||
|
"Phi": 0.0,
|
||||||
|
"Power": {
|
||||||
|
"Active": 0.0,
|
||||||
|
"Reactive": 0.0,
|
||||||
|
"Apparent": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"L3": {
|
||||||
|
"Voltage": 239.5,
|
||||||
|
"Current": 0.0,
|
||||||
|
"Phi": 0.0,
|
||||||
|
"Power": {
|
||||||
|
"Active": 0.0,
|
||||||
|
"Reactive": 0.0,
|
||||||
|
"Apparent": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Frequency": 50.0,
|
||||||
|
"Power": {
|
||||||
|
"Active": 0.0,
|
||||||
|
"Reactive": 0.0,
|
||||||
|
"Apparent": 0.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ActivePowerImportT1": 58082.0,
|
||||||
|
"ActivePowerExportT1": 1569.0,
|
||||||
|
"ActivePowerImportT2": 58082.0,
|
||||||
|
"ActivePowerExportT2": 1569.0,
|
||||||
|
"ActivePowerImportT3": 123.0,
|
||||||
|
"ActivePowerExportT3": 1.0,
|
||||||
|
"ActivePowerImportT4": 0.0,
|
||||||
|
"ActivePowerExportT4": 0.0
|
||||||
|
},
|
||||||
|
"LoadOnAcGrid": {
|
||||||
|
"Power": {
|
||||||
|
"Active": 1306.05,
|
||||||
|
"Reactive": -184.15,
|
||||||
|
"Apparent": 1318.97
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AcGridToAcIsland": {
|
||||||
|
"Power": {
|
||||||
|
"Active": -1414.36,
|
||||||
|
"Reactive": -232.31,
|
||||||
|
"Apparent": 1433.31
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"AcDcToDcLink": {
|
||||||
|
"Power": -1414.36
|
||||||
|
},
|
||||||
|
"LoadOnDc": {
|
||||||
|
"Power": -321.32
|
||||||
|
},
|
||||||
|
"Relays": {
|
||||||
|
"K1GridBusIsConnectedToGrid": "True",
|
||||||
|
"K2IslandBusIsConnectedToGridBus": "True",
|
||||||
|
"K3Inverter1IsConnectedToIslandBus": "True",
|
||||||
|
"K3Inverter2IsConnectedToIslandBus": "True",
|
||||||
|
"K3Inverter3IsConnectedToIslandBus": "True",
|
||||||
|
"K3Inverter4IsConnectedToIslandBus": "True",
|
||||||
|
"FiWarning": "False",
|
||||||
|
"FiError": "False",
|
||||||
|
"K2ConnectIslandBusToGridBus": "True"
|
||||||
|
},
|
||||||
|
"PvOnDc": {
|
||||||
|
"Dc": {
|
||||||
|
"Voltage": 779.07,
|
||||||
|
"Current": 1.4,
|
||||||
|
"Power": 1093.03
|
||||||
|
},
|
||||||
|
"NbrOfStrings": 3.0,
|
||||||
|
"Strings": {
|
||||||
|
"1": {
|
||||||
|
"Voltage": 779.25,
|
||||||
|
"Current": 0.5,
|
||||||
|
"Power": 391.96
|
||||||
|
},
|
||||||
|
"2": {
|
||||||
|
"Voltage": 779.1,
|
||||||
|
"Current": 0.52,
|
||||||
|
"Power": 407.47
|
||||||
|
},
|
||||||
|
"3": {
|
||||||
|
"Voltage": 778.86,
|
||||||
|
"Current": 0.38,
|
||||||
|
"Power": 293.63
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"DcWh": 137.11
|
||||||
|
},
|
||||||
|
"Config": {
|
||||||
|
"MinSoc": 10.0,
|
||||||
|
"CurtailP": 5.0,
|
||||||
|
"PvInstalledPower": 0.0,
|
||||||
|
"ForceCalibrationChargeState": "RepetitivelyEvery",
|
||||||
|
"DayAndTimeForRepetitiveCalibration": "05/29/2025 09:00:00",
|
||||||
|
"DayAndTimeForAdditionalCalibration": "05/23/2025 15:46:00",
|
||||||
|
"ForceCalibrationDischargeState": "RepetitivelyEvery",
|
||||||
|
"DownDayAndTimeForRepetitiveCalibration": "06/23/2025 19:00:00",
|
||||||
|
"DownDayAndTimeForAdditionalCalibration": "01/01/0001 00:00:00",
|
||||||
|
"DisplayIndividualBatteries": "False",
|
||||||
|
"PConstant": 0.5,
|
||||||
|
"GridSetPoint": 0.0,
|
||||||
|
"BatterySelfDischargePower": 200.0,
|
||||||
|
"HoldSocZone": 1.0,
|
||||||
|
"IslandMode": {
|
||||||
|
"AcDc": {
|
||||||
|
"MaxDcLinkVoltage": 930.0,
|
||||||
|
"MinDcLinkVoltage": 690.0,
|
||||||
|
"ReferenceDcLinkVoltage": 750.0
|
||||||
|
},
|
||||||
|
"DcDc": {
|
||||||
|
"LowerDcLinkVoltage": 50.0,
|
||||||
|
"ReferenceDcLinkVoltage": 750.0,
|
||||||
|
"UpperDcLinkVoltage": 50.0,
|
||||||
|
"MaxBatteryChargingCurrent": 210.0,
|
||||||
|
"MaxBatteryDischargingCurrent": 210.0,
|
||||||
|
"MaxDcPower": 10000.0,
|
||||||
|
"MaxChargeBatteryVoltage": 63.0,
|
||||||
|
"MinDischargeBatteryVoltage": 32.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"GridTie": {
|
||||||
|
"AcDc": {
|
||||||
|
"MaxDcLinkVoltage": 780.0,
|
||||||
|
"MinDcLinkVoltage": 720.0,
|
||||||
|
"ReferenceDcLinkVoltage": 750.0
|
||||||
|
},
|
||||||
|
"DcDc": {
|
||||||
|
"LowerDcLinkVoltage": 20.0,
|
||||||
|
"ReferenceDcLinkVoltage": 750.0,
|
||||||
|
"UpperDcLinkVoltage": 20.0,
|
||||||
|
"MaxBatteryChargingCurrent": 210.0,
|
||||||
|
"MaxBatteryDischargingCurrent": 210.0,
|
||||||
|
"MaxDcPower": 10000.0,
|
||||||
|
"MaxChargeBatteryVoltage": 63.0,
|
||||||
|
"MinDischargeBatteryVoltage": 32.0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Devices": {
|
||||||
|
"RelaysIp": {
|
||||||
|
"DeviceState": "Measured",
|
||||||
|
"Host": "10.0.1.1",
|
||||||
|
"Port": 502.0
|
||||||
|
},
|
||||||
|
"TsRelaysIp": {
|
||||||
|
"DeviceState": "Measured",
|
||||||
|
"Host": "10.0.1.2",
|
||||||
|
"Port": 502.0
|
||||||
|
},
|
||||||
|
"GridMeterIp": {
|
||||||
|
"DeviceState": "Measured",
|
||||||
|
"Host": "10.0.4.1",
|
||||||
|
"Port": 502.0
|
||||||
|
},
|
||||||
|
"PvOnAcGrid": {
|
||||||
|
"DeviceState": "Disabled",
|
||||||
|
"Host": "false",
|
||||||
|
"Port": 0.0
|
||||||
|
},
|
||||||
|
"LoadOnAcGrid": {
|
||||||
|
"DeviceState": "Measured",
|
||||||
|
"Host": "true",
|
||||||
|
"Port": 0.0
|
||||||
|
},
|
||||||
|
"PvOnAcIsland": {
|
||||||
|
"DeviceState": "Disabled",
|
||||||
|
"Host": "false",
|
||||||
|
"Port": 0.0
|
||||||
|
},
|
||||||
|
"IslandBusLoadMeterIp": {
|
||||||
|
"DeviceState": "Measured",
|
||||||
|
"Host": "10.0.4.2",
|
||||||
|
"Port": 502.0
|
||||||
|
},
|
||||||
|
"TruConvertAcIp": {
|
||||||
|
"DeviceState": "Measured",
|
||||||
|
"Host": "10.0.2.1",
|
||||||
|
"Port": 502.0
|
||||||
|
},
|
||||||
|
"PvOnDc": {
|
||||||
|
"DeviceState": "Measured",
|
||||||
|
"Host": "10.0.5.1",
|
||||||
|
"Port": 502.0
|
||||||
|
},
|
||||||
|
"LoadOnDc": {
|
||||||
|
"DeviceState": "Measured",
|
||||||
|
"Host": "false",
|
||||||
|
"Port": 0.0
|
||||||
|
},
|
||||||
|
"TruConvertDcIp": {
|
||||||
|
"DeviceState": "Measured",
|
||||||
|
"Host": "10.0.3.1",
|
||||||
|
"Port": 502.0
|
||||||
|
},
|
||||||
|
"BatteryIp": {
|
||||||
|
"DeviceState": "Measured",
|
||||||
|
"Host": "localhost",
|
||||||
|
"Port": 6855.0
|
||||||
|
},
|
||||||
|
"BatteryNodes": "0,1,2,3,4,5"
|
||||||
|
},
|
||||||
|
"S3": {
|
||||||
|
"Bucket": "1-3e5b3069-214a-43ee-8d85-57d72000c19d",
|
||||||
|
"Region": "sos-ch-dk-2",
|
||||||
|
"Provider": "exo.io",
|
||||||
|
"Key": "EXO1752677fa3b7a5dc1b4efcb9",
|
||||||
|
"Secret": "fUTGbI-I29dPdS9KrJxpnrpBcWbcpAZmoYcECfVEiYU",
|
||||||
|
"ContentType": "text/plain",
|
||||||
|
"Host": "1-3e5b3069-214a-43ee-8d85-57d72000c19d.sos-ch-dk-2.exo.io",
|
||||||
|
"Url": "https://1-3e5b3069-214a-43ee-8d85-57d72000c19d.sos-ch-dk-2.exo.io"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Log": {
|
||||||
|
"SalimaxAlarmState": "Green"
|
||||||
|
},
|
||||||
|
"EssControl": {
|
||||||
|
"Mode": "UpwardsCalibrationCharge",
|
||||||
|
"LimitedBy": "ChargeLimitedByMaxDcBusVoltage",
|
||||||
|
"PowerCorrection": -355.15,
|
||||||
|
"PowerSetpoint": 22.85
|
||||||
|
},
|
||||||
|
"StateMachine": {
|
||||||
|
"Message": "ESS",
|
||||||
|
"State": 23.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,256 @@
|
||||||
|
import os
|
||||||
|
import csv
|
||||||
|
import subprocess
|
||||||
|
import argparse
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from collections import defaultdict
|
||||||
|
import zipfile
|
||||||
|
import base64
|
||||||
|
import shutil
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def extract_timestamp(filename):
|
||||||
|
timestamp_str = filename[:10]
|
||||||
|
try:
|
||||||
|
timestamp = int(timestamp_str)
|
||||||
|
return timestamp
|
||||||
|
except ValueError:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def list_files_in_range(start_timestamp, end_timestamp, sampling_stepsize,product_type,bucket_number):
|
||||||
|
if product_type == "Salimax" or product_type=="SodistoreMax":
|
||||||
|
hash = "3e5b3069-214a-43ee-8d85-57d72000c19d"
|
||||||
|
elif product_type == "Salidomo":
|
||||||
|
hash = "c0436b6a-d276-4cd8-9c44-1eae86cf5d0e"
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid product type option. Use Salimax or Salidomo or SodistoreMax")
|
||||||
|
|
||||||
|
# Find common prefix
|
||||||
|
common_prefix = ""
|
||||||
|
for s_char, e_char in zip(str(start_timestamp), str(end_timestamp)):
|
||||||
|
if s_char == e_char:
|
||||||
|
common_prefix += s_char
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
s3_path = f"s3://{bucket_number}-{hash}/{common_prefix}*"
|
||||||
|
s3cmd_command = f"s3cmd ls {s3_path}"
|
||||||
|
|
||||||
|
print(f"Running: {s3cmd_command}")
|
||||||
|
try:
|
||||||
|
output = subprocess.check_output(s3cmd_command, shell=True, text=True)
|
||||||
|
files = [line.split()[-1] for line in output.strip().split("\n") if line.strip()]
|
||||||
|
filenames = []
|
||||||
|
for f in files:
|
||||||
|
name = f.split("/")[-1] # e.g., 1748802020.json
|
||||||
|
timestamp_str = name.split(".")[0] # extract '1748802020'
|
||||||
|
if timestamp_str.isdigit() and int(timestamp_str) <= int(end_timestamp):
|
||||||
|
filenames.append(name)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
print(filenames)
|
||||||
|
return filenames
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
print(f"No files found for prefix {common_prefix}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_nested_value(data, key_path):
|
||||||
|
try:
|
||||||
|
for key in key_path:
|
||||||
|
data = data[key]
|
||||||
|
return data
|
||||||
|
except (KeyError, TypeError):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def process_json_files_to_csv(output_directory, json_files, keys, start_timestamp, end_timestamp, bucket_number, booleans_as_numbers):
|
||||||
|
# Generate output file name from all keys
|
||||||
|
keypath = '_'.join(get_last_component(k) for k in keys)
|
||||||
|
output_csv_filename = f"{keypath}_from_{start_timestamp}_to_{end_timestamp}_bucket_{bucket_number}.csv"
|
||||||
|
|
||||||
|
with open(output_csv_filename, 'w', newline='') as csvfile:
|
||||||
|
csv_writer = csv.writer(csvfile)
|
||||||
|
|
||||||
|
# Write header: 'time' + key names
|
||||||
|
header = ['time'] + [k.split('/')[-1] for k in keys]
|
||||||
|
csv_writer.writerow(header)
|
||||||
|
|
||||||
|
for json_file in json_files:
|
||||||
|
file_path = os.path.join(output_directory, json_file)
|
||||||
|
with open(file_path, 'r') as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
while i < len(lines) - 1:
|
||||||
|
timestamp_line = lines[i].strip()
|
||||||
|
json_line = lines[i + 1].strip()
|
||||||
|
i += 2
|
||||||
|
|
||||||
|
if not timestamp_line.startswith("Timestamp;"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
timestamp = int(timestamp_line.split(';')[1])
|
||||||
|
except ValueError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not (start_timestamp <= timestamp <= end_timestamp):
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
data = json.loads(json_line)
|
||||||
|
except json.JSONDecodeError:
|
||||||
|
print(f"❌ Failed to parse JSON in {json_file}, line {i}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
row = [timestamp]
|
||||||
|
|
||||||
|
for key in keys:
|
||||||
|
value = get_nested_value(data, key.split('/'))
|
||||||
|
|
||||||
|
if booleans_as_numbers and isinstance(value, str) and value.lower() in ["true", "false"]:
|
||||||
|
value = 1 if value.lower() == "true" else 0
|
||||||
|
if value is None:
|
||||||
|
value = "No value provided"
|
||||||
|
|
||||||
|
row.append(value)
|
||||||
|
|
||||||
|
csv_writer.writerow(row)
|
||||||
|
|
||||||
|
print(f"✅ Extracted data saved in '{output_csv_filename}'")
|
||||||
|
|
||||||
|
|
||||||
|
def download_files(bucket_number, filenames_to_download, product_type):
|
||||||
|
if product_type == "Salimax" or product_type=="SodistoreMax":
|
||||||
|
hash = "3e5b3069-214a-43ee-8d85-57d72000c19d"
|
||||||
|
elif product_type == "Salidomo":
|
||||||
|
hash = "c0436b6a-d276-4cd8-9c44-1eae86cf5d0e"
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid product type option. Use Salimax or Salidomo or SodistoreMax")
|
||||||
|
output_directory = f"S3cmdData_{bucket_number}"
|
||||||
|
|
||||||
|
if not os.path.exists(output_directory):
|
||||||
|
os.makedirs(output_directory)
|
||||||
|
print(f"Directory '{output_directory}' created.")
|
||||||
|
|
||||||
|
for filename in filenames_to_download:
|
||||||
|
print(filename)
|
||||||
|
|
||||||
|
local_path = os.path.join(output_directory, filename)
|
||||||
|
if not os.path.exists(local_path):
|
||||||
|
s3cmd_command = f"s3cmd get s3://{bucket_number}-{hash}/{filename} {output_directory}/"
|
||||||
|
|
||||||
|
try:
|
||||||
|
subprocess.run(s3cmd_command, shell=True, check=True)
|
||||||
|
downloaded_files = [file for file in os.listdir(output_directory) if file.startswith(filename)]
|
||||||
|
if not downloaded_files:
|
||||||
|
print(f"No matching files found for prefix '{filename}'.")
|
||||||
|
else:
|
||||||
|
print(f"Files with prefix '{filename}' downloaded successfully.")
|
||||||
|
decompress_file(os.path.join(output_directory, filename), output_directory)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
# print(f"Error downloading files: {e}")
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
print(f"File '{filename}.json' already exists locally. Skipping download.")
|
||||||
|
|
||||||
|
def decompress_file(compressed_file, output_directory):
|
||||||
|
base_name = os.path.splitext(os.path.basename(compressed_file))[0]
|
||||||
|
|
||||||
|
with open(compressed_file, 'rb') as file:
|
||||||
|
compressed_data = file.read()
|
||||||
|
|
||||||
|
# Decode the base64 encoded content
|
||||||
|
decoded_data = base64.b64decode(compressed_data)
|
||||||
|
|
||||||
|
zip_path = os.path.join(output_directory, 'temp.zip')
|
||||||
|
with open(zip_path, 'wb') as zip_file:
|
||||||
|
zip_file.write(decoded_data)
|
||||||
|
|
||||||
|
with zipfile.ZipFile(zip_path, 'r') as zip_ref:
|
||||||
|
zip_ref.extractall(output_directory)
|
||||||
|
|
||||||
|
# Rename the extracted data.json file to the original timestamp-based name
|
||||||
|
extracted_csv_path = os.path.join(output_directory, 'data.json')
|
||||||
|
if os.path.exists(extracted_csv_path):
|
||||||
|
new_csv_path = os.path.join(output_directory, f"{base_name}.json")
|
||||||
|
|
||||||
|
os.rename(extracted_csv_path, new_csv_path)
|
||||||
|
|
||||||
|
os.remove(zip_path)
|
||||||
|
print(f"Decompressed and renamed '{compressed_file}' to '{new_csv_path}'.")
|
||||||
|
|
||||||
|
|
||||||
|
def get_last_component(path):
|
||||||
|
path_without_slashes = path.replace('/', '')
|
||||||
|
return path_without_slashes
|
||||||
|
|
||||||
|
def download_and_process_files(bucket_number, start_timestamp, end_timestamp, sampling_stepsize, keys, booleans_as_numbers, exact_match, product_type):
|
||||||
|
output_directory = f"S3cmdData_{bucket_number}"
|
||||||
|
|
||||||
|
#if os.path.exists(output_directory):
|
||||||
|
# shutil.rmtree(output_directory)
|
||||||
|
|
||||||
|
if not os.path.exists(output_directory):
|
||||||
|
os.makedirs(output_directory)
|
||||||
|
print(f"Directory '{output_directory}' created.")
|
||||||
|
|
||||||
|
filenames_to_check = list_files_in_range(start_timestamp, end_timestamp, sampling_stepsize,product_type,bucket_number)
|
||||||
|
existing_files = [filename for filename in filenames_to_check if os.path.exists(os.path.join(output_directory, f"{filename}.json"))]
|
||||||
|
files_to_download = set(filenames_to_check) - set(existing_files)
|
||||||
|
print(files_to_download)
|
||||||
|
|
||||||
|
#if os.listdir(output_directory):
|
||||||
|
# print("Files already exist in the local folder. Skipping download.")
|
||||||
|
#else:
|
||||||
|
if files_to_download:
|
||||||
|
download_files(bucket_number, files_to_download, product_type)
|
||||||
|
|
||||||
|
json_files = [file for file in os.listdir(output_directory) if file.endswith('.json')]
|
||||||
|
json_files.sort(key=extract_timestamp)
|
||||||
|
|
||||||
|
process_json_files_to_csv(
|
||||||
|
output_directory=output_directory,
|
||||||
|
json_files=json_files,
|
||||||
|
keys=keys,
|
||||||
|
start_timestamp=start_timestamp,
|
||||||
|
end_timestamp=end_timestamp,
|
||||||
|
bucket_number=bucket_number,
|
||||||
|
booleans_as_numbers=booleans_as_numbers
|
||||||
|
)
|
||||||
|
|
||||||
|
def parse_keys(input_string):
|
||||||
|
keys = [key.strip() for key in input_string.split(',')]
|
||||||
|
return keys
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description='Download files from S3 using s3cmd and extract specific values from CSV files.')
|
||||||
|
parser.add_argument('start_timestamp', type=int, help='The start timestamp for the range (even number)')
|
||||||
|
parser.add_argument('end_timestamp', type=int, help='The end timestamp for the range (even number)')
|
||||||
|
parser.add_argument('--keys', type=parse_keys, required=True, help='The part to match from each CSV file, can be a single key or a comma-separated list of keys')
|
||||||
|
parser.add_argument('--bucket-number', type=int, required=True, help='The number of the bucket to download from')
|
||||||
|
parser.add_argument('--sampling_stepsize', type=int, required=False, default=1, help='The number of 2sec intervals, which define the length of the sampling interval in S3 file retrieval')
|
||||||
|
parser.add_argument('--booleans_as_numbers', action="store_true", required=False, help='If key used, then booleans are converted to numbers [0/1], if key not used, then booleans maintained as text [False/True]')
|
||||||
|
parser.add_argument('--exact_match', action="store_true", required=False, help='If key used, then key has to match exactly "=", else it is enough that key is found "in" text')
|
||||||
|
parser.add_argument('--product_name', required=True, help='Use Salimax, Salidomo or SodistoreMax')
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
start_timestamp = args.start_timestamp
|
||||||
|
end_timestamp = args.end_timestamp
|
||||||
|
keys = args.keys
|
||||||
|
bucket_number = args.bucket_number
|
||||||
|
sampling_stepsize = args.sampling_stepsize
|
||||||
|
booleans_as_numbers = args.booleans_as_numbers
|
||||||
|
exact_match = args.exact_match
|
||||||
|
# new arg for product type
|
||||||
|
product_type = args.product_name
|
||||||
|
|
||||||
|
if start_timestamp >= end_timestamp:
|
||||||
|
print("Error: start_timestamp must be smaller than end_timestamp.")
|
||||||
|
return
|
||||||
|
download_and_process_files(bucket_number, start_timestamp, end_timestamp, sampling_stepsize, keys, booleans_as_numbers, exact_match, product_type)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
using System.Diagnostics;
|
||||||
|
using InnovEnergy.App.Backend.Database;
|
||||||
|
using InnovEnergy.App.Backend.DataTypes;
|
||||||
|
using InnovEnergy.Lib.Utils;
|
||||||
|
|
||||||
|
namespace InnovEnergy.App.Backend.DeleteOldData;
|
||||||
|
|
||||||
|
public class DeleteOldDataFromS3
|
||||||
|
{
|
||||||
|
|
||||||
|
public static void DeleteFrom(Installation installation, int timestamps_to_delete)
|
||||||
|
{
|
||||||
|
|
||||||
|
string configPath = "/home/ubuntu/.s3cfg";
|
||||||
|
string bucketPath = installation.Product ==(int)ProductType.Salidomo ? $"s3://{installation.S3BucketId}-c0436b6a-d276-4cd8-9c44-1eae86cf5d0e/{timestamps_to_delete}*" : $"s3://{installation.S3BucketId}-3e5b3069-214a-43ee-8d85-57d72000c19d/{timestamps_to_delete}*" ;
|
||||||
|
|
||||||
|
//Console.WriteLine($"Deleting old data from {bucketPath}");
|
||||||
|
|
||||||
|
Console.WriteLine("Deleting data for timestamp prefix: " + timestamps_to_delete);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ProcessStartInfo startInfo = new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = "s3cmd",
|
||||||
|
Arguments = $"--config {configPath} rm {bucketPath}",
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
UseShellExecute = false,
|
||||||
|
CreateNoWindow = true
|
||||||
|
};
|
||||||
|
|
||||||
|
using Process process = new Process { StartInfo = startInfo };
|
||||||
|
|
||||||
|
process.OutputDataReceived += (sender, e) =>
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(e.Data))
|
||||||
|
Console.WriteLine("[s3cmd] " + e.Data);
|
||||||
|
};
|
||||||
|
|
||||||
|
process.ErrorDataReceived += (sender, e) =>
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(e.Data))
|
||||||
|
Console.WriteLine("[s3cmd-ERR] " + e.Data);
|
||||||
|
};
|
||||||
|
|
||||||
|
process.Start();
|
||||||
|
process.BeginOutputReadLine();
|
||||||
|
process.BeginErrorReadLine();
|
||||||
|
process.WaitForExit();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Exception occurred during deletion: " + ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async Task DeleteOldData()
|
||||||
|
{
|
||||||
|
while (true){
|
||||||
|
var installations = Db.Installations.ToList();
|
||||||
|
foreach (var installation in installations){
|
||||||
|
Console.WriteLine("DELETE S3 DATA FOR INSTALLATION "+installation.Name);
|
||||||
|
long oneYearAgoTimestamp = DateTimeOffset.UtcNow.AddYears(-1).ToUnixTimeSeconds();
|
||||||
|
|
||||||
|
Console.WriteLine("delete data before "+oneYearAgoTimestamp);
|
||||||
|
for (int lastDigit=4;lastDigit>=0; lastDigit--)
|
||||||
|
{
|
||||||
|
int timestamps_to_delete = int.Parse(oneYearAgoTimestamp.ToString().Substring(0, lastDigit+1));
|
||||||
|
timestamps_to_delete--;
|
||||||
|
Console.WriteLine(timestamps_to_delete);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (timestamps_to_delete % 10 == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("delete " + timestamps_to_delete + "*");
|
||||||
|
DeleteFrom(installation,timestamps_to_delete);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Console.WriteLine("delete " + timestamps_to_delete + "*");
|
||||||
|
DeleteFrom(installation,timestamps_to_delete);
|
||||||
|
timestamps_to_delete--;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Console.WriteLine("FINISHED DELETING S3 DATA FOR ALL INSTALLATIONS\n");
|
||||||
|
|
||||||
|
await Task.Delay(TimeSpan.FromDays(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ using Flurl.Http;
|
||||||
using Hellang.Middleware.ProblemDetails;
|
using Hellang.Middleware.ProblemDetails;
|
||||||
using InnovEnergy.App.Backend.Database;
|
using InnovEnergy.App.Backend.Database;
|
||||||
using InnovEnergy.App.Backend.Websockets;
|
using InnovEnergy.App.Backend.Websockets;
|
||||||
|
using InnovEnergy.App.Backend.DeleteOldData;
|
||||||
using Microsoft.AspNetCore.HttpOverrides;
|
using Microsoft.AspNetCore.HttpOverrides;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
|
|
@ -30,6 +31,9 @@ public static class Program
|
||||||
WebsocketManager.MonitorSalimaxInstallationTable().SupressAwaitWarning();
|
WebsocketManager.MonitorSalimaxInstallationTable().SupressAwaitWarning();
|
||||||
WebsocketManager.MonitorSalidomoInstallationTable().SupressAwaitWarning();
|
WebsocketManager.MonitorSalidomoInstallationTable().SupressAwaitWarning();
|
||||||
WebsocketManager.MonitorSodistoreInstallationTable().SupressAwaitWarning();
|
WebsocketManager.MonitorSodistoreInstallationTable().SupressAwaitWarning();
|
||||||
|
|
||||||
|
|
||||||
|
Task.Run(() => DeleteOldDataFromS3.DeleteOldData());
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
builder.Services.AddProblemDetails(setup =>
|
builder.Services.AddProblemDetails(setup =>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ public static class WebsocketManager
|
||||||
{
|
{
|
||||||
while (true){
|
while (true){
|
||||||
lock (InstallationConnections){
|
lock (InstallationConnections){
|
||||||
Console.WriteLine("MONITOR SALIMAX INSTALLATIONS\n");
|
// Console.WriteLine("MONITOR SALIMAX INSTALLATIONS\n");
|
||||||
foreach (var installationConnection in InstallationConnections){
|
foreach (var installationConnection in InstallationConnections){
|
||||||
|
|
||||||
if (installationConnection.Value.Product==(int)ProductType.Salimax && (DateTime.Now - installationConnection.Value.Timestamp) > TimeSpan.FromMinutes(2)){
|
if (installationConnection.Value.Product==(int)ProductType.Salimax && (DateTime.Now - installationConnection.Value.Timestamp) > TimeSpan.FromMinutes(2)){
|
||||||
|
|
@ -35,7 +35,7 @@ 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 MONITORING SALIMAX INSTALLATIONS\n");
|
// Console.WriteLine("FINISHED MONITORING SALIMAX INSTALLATIONS\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
await Task.Delay(TimeSpan.FromMinutes(1));
|
await Task.Delay(TimeSpan.FromMinutes(1));
|
||||||
|
|
@ -47,15 +47,15 @@ public static class WebsocketManager
|
||||||
public static async Task MonitorSalidomoInstallationTable()
|
public static async Task MonitorSalidomoInstallationTable()
|
||||||
{
|
{
|
||||||
while (true){
|
while (true){
|
||||||
Console.WriteLine("TRY TO LOCK FOR MONITOR SALIDOMO INSTALLATIONS\n");
|
//Console.WriteLine("TRY TO LOCK FOR MONITOR SALIDOMO INSTALLATIONS\n");
|
||||||
lock (InstallationConnections){
|
lock (InstallationConnections){
|
||||||
Console.WriteLine("MONITOR SALIDOMO INSTALLATIONS\n");
|
//Console.WriteLine("MONITOR SALIDOMO INSTALLATIONS\n");
|
||||||
foreach (var installationConnection in InstallationConnections)
|
foreach (var installationConnection in InstallationConnections)
|
||||||
{
|
{
|
||||||
//Console.WriteLine("Installation ID is "+installationConnection.Key);
|
//Console.WriteLine("Installation ID is "+installationConnection.Key);
|
||||||
if (installationConnection.Value.Product == (int)ProductType.Salidomo && (DateTime.Now - installationConnection.Value.Timestamp) < TimeSpan.FromMinutes(60)){
|
// if (installationConnection.Value.Product == (int)ProductType.Salidomo && (DateTime.Now - installationConnection.Value.Timestamp) < TimeSpan.FromMinutes(60)){
|
||||||
Console.WriteLine("Installation ID is "+installationConnection.Key + " diff is "+(DateTime.Now-installationConnection.Value.Timestamp));
|
// Console.WriteLine("Installation ID is "+installationConnection.Key + " diff is "+(DateTime.Now-installationConnection.Value.Timestamp));
|
||||||
}
|
// }
|
||||||
|
|
||||||
if (installationConnection.Value.Product==(int)ProductType.Salidomo && (DateTime.Now - installationConnection.Value.Timestamp) > TimeSpan.FromMinutes(60))
|
if (installationConnection.Value.Product==(int)ProductType.Salidomo && (DateTime.Now - installationConnection.Value.Timestamp) > TimeSpan.FromMinutes(60))
|
||||||
{
|
{
|
||||||
|
|
@ -64,16 +64,16 @@ public static class WebsocketManager
|
||||||
//Console.WriteLine("timestamp now is is "+(DateTime.Now));
|
//Console.WriteLine("timestamp now is is "+(DateTime.Now));
|
||||||
|
|
||||||
Installation installation = Db.Installations.FirstOrDefault(f => f.Product == (int)ProductType.Salidomo && f.Id == installationConnection.Key);
|
Installation installation = Db.Installations.FirstOrDefault(f => f.Product == (int)ProductType.Salidomo && f.Id == installationConnection.Key);
|
||||||
Console.WriteLine("Installation ID is "+installation.Name + " diff is "+(DateTime.Now-installationConnection.Value.Timestamp));
|
//Console.WriteLine("Installation ID is "+installation.Name + " diff is "+(DateTime.Now-installationConnection.Value.Timestamp));
|
||||||
installation.Status = (int)StatusType.Offline;
|
installation.Status = (int)StatusType.Offline;
|
||||||
installation.Apply(Db.Update);
|
installation.Apply(Db.Update);
|
||||||
|
|
||||||
installationConnection.Value.Status = (int)StatusType.Offline;
|
installationConnection.Value.Status = (int)StatusType.Offline;
|
||||||
if (installationConnection.Value.Connections.Count > 0){InformWebsocketsForInstallation(installationConnection.Key);}
|
if (installationConnection.Value.Connections.Count > 0){InformWebsocketsForInstallation(installationConnection.Key);}
|
||||||
else{Console.WriteLine("NONE IS CONNECTED TO THAT INSTALLATION-------------------------------------------------------------");}
|
//else{Console.WriteLine("NONE IS CONNECTED TO THAT INSTALLATION-------------------------------------------------------------");}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Console.WriteLine("FINISHED WITH UPDATING\n");
|
//Console.WriteLine("FINISHED WITH UPDATING\n");
|
||||||
}
|
}
|
||||||
await Task.Delay(TimeSpan.FromMinutes(1));
|
await Task.Delay(TimeSpan.FromMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
@ -84,9 +84,9 @@ public static class WebsocketManager
|
||||||
public static async Task MonitorSodistoreInstallationTable()
|
public static async Task MonitorSodistoreInstallationTable()
|
||||||
{
|
{
|
||||||
while (true){
|
while (true){
|
||||||
Console.WriteLine("TRY TO LOCK FOR MONITOR SODISTORE INSTALLATIONS\n");
|
//Console.WriteLine("TRY TO LOCK FOR MONITOR SODISTORE INSTALLATIONS\n");
|
||||||
lock (InstallationConnections){
|
lock (InstallationConnections){
|
||||||
Console.WriteLine("MONITOR SODISTORE INSTALLATIONS\n");
|
//Console.WriteLine("MONITOR SODISTORE INSTALLATIONS\n");
|
||||||
foreach (var installationConnection in InstallationConnections)
|
foreach (var installationConnection in InstallationConnections)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -97,16 +97,16 @@ public static class WebsocketManager
|
||||||
//Console.WriteLine("timestamp now is is "+(DateTime.Now));
|
//Console.WriteLine("timestamp now is is "+(DateTime.Now));
|
||||||
|
|
||||||
Installation installation = Db.Installations.FirstOrDefault(f => f.Product == (int)ProductType.SodiStoreMax && f.Id == installationConnection.Key);
|
Installation installation = Db.Installations.FirstOrDefault(f => f.Product == (int)ProductType.SodiStoreMax && f.Id == installationConnection.Key);
|
||||||
Console.WriteLine("Installation ID is "+installation.Name + " diff is "+(DateTime.Now-installationConnection.Value.Timestamp));
|
//Console.WriteLine("Installation ID is "+installation.Name + " diff is "+(DateTime.Now-installationConnection.Value.Timestamp));
|
||||||
installation.Status = (int)StatusType.Offline;
|
installation.Status = (int)StatusType.Offline;
|
||||||
installation.Apply(Db.Update);
|
installation.Apply(Db.Update);
|
||||||
|
|
||||||
installationConnection.Value.Status = (int)StatusType.Offline;
|
installationConnection.Value.Status = (int)StatusType.Offline;
|
||||||
if (installationConnection.Value.Connections.Count > 0){InformWebsocketsForInstallation(installationConnection.Key);}
|
if (installationConnection.Value.Connections.Count > 0){InformWebsocketsForInstallation(installationConnection.Key);}
|
||||||
else{Console.WriteLine("NONE IS CONNECTED TO THAT INSTALLATION-------------------------------------------------------------");}
|
//else{Console.WriteLine("NONE IS CONNECTED TO THAT INSTALLATION-------------------------------------------------------------");}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Console.WriteLine("FINISHED WITH UPDATING\n");
|
//Console.WriteLine("FINISHED WITH UPDATING\n");
|
||||||
}
|
}
|
||||||
await Task.Delay(TimeSpan.FromMinutes(1));
|
await Task.Delay(TimeSpan.FromMinutes(1));
|
||||||
}
|
}
|
||||||
|
|
@ -225,20 +225,20 @@ public static class WebsocketManager
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
Console.WriteLine("Printing installation connection list");
|
// Console.WriteLine("Printing installation connection list");
|
||||||
Console.WriteLine("----------------------------------------------");
|
// Console.WriteLine("----------------------------------------------");
|
||||||
foreach (var installationConnection in InstallationConnections)
|
// foreach (var installationConnection in InstallationConnections)
|
||||||
{
|
// {
|
||||||
Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count);
|
// Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count);
|
||||||
}
|
// }
|
||||||
Console.WriteLine("----------------------------------------------");
|
// Console.WriteLine("----------------------------------------------");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (InstallationConnections)
|
lock (InstallationConnections)
|
||||||
{
|
{
|
||||||
//When the front-end terminates the connection, the following code will be executed
|
//When the front-end terminates the connection, the following code will be executed
|
||||||
Console.WriteLine("The connection has been terminated");
|
//Console.WriteLine("The connection has been terminated");
|
||||||
foreach (var installationConnection in InstallationConnections)
|
foreach (var installationConnection in InstallationConnections)
|
||||||
{
|
{
|
||||||
if (installationConnection.Value.Connections.Contains(currentWebSocket))
|
if (installationConnection.Value.Connections.Contains(currentWebSocket))
|
||||||
|
|
@ -249,18 +249,18 @@ public static class WebsocketManager
|
||||||
}
|
}
|
||||||
|
|
||||||
await currentWebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Connection closed by server", CancellationToken.None);
|
await currentWebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Connection closed by server", CancellationToken.None);
|
||||||
lock (InstallationConnections)
|
// lock (InstallationConnections)
|
||||||
{
|
// {
|
||||||
//Print the installationConnections dictionary after deleting a websocket
|
// //Print the installationConnections dictionary after deleting a websocket
|
||||||
Console.WriteLine("Print the installation connections list after deleting a websocket");
|
// Console.WriteLine("Print the installation connections list after deleting a websocket");
|
||||||
Console.WriteLine("----------------------------------------------");
|
// Console.WriteLine("----------------------------------------------");
|
||||||
foreach (var installationConnection in InstallationConnections)
|
// foreach (var installationConnection in InstallationConnections)
|
||||||
{
|
// {
|
||||||
Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count);
|
// Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
Console.WriteLine("----------------------------------------------");
|
// Console.WriteLine("----------------------------------------------");
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@
|
||||||
"react-cytoscapejs": "^2.0.0",
|
"react-cytoscapejs": "^2.0.0",
|
||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2",
|
||||||
"react-flow-renderer": "^10.3.17",
|
"react-flow-renderer": "^10.3.17",
|
||||||
|
"react-gauge-chart": "^0.5.1",
|
||||||
"react-helmet-async": "1.3.0",
|
"react-helmet-async": "1.3.0",
|
||||||
"react-icons": "^4.11.0",
|
"react-icons": "^4.11.0",
|
||||||
"react-icons-converter": "^1.1.4",
|
"react-icons-converter": "^1.1.4",
|
||||||
|
|
@ -7737,6 +7738,51 @@
|
||||||
"resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz",
|
"resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz",
|
||||||
"integrity": "sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg=="
|
"integrity": "sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/d3-array": {
|
||||||
|
"version": "3.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
|
||||||
|
"integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
|
||||||
|
"dependencies": {
|
||||||
|
"internmap": "1 - 2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-axis": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-brush": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-dispatch": "1 - 3",
|
||||||
|
"d3-drag": "2 - 3",
|
||||||
|
"d3-interpolate": "1 - 3",
|
||||||
|
"d3-selection": "3",
|
||||||
|
"d3-transition": "3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-chord": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-path": "1 - 3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/d3-color": {
|
"node_modules/d3-color": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
|
||||||
|
|
@ -7745,6 +7791,28 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/d3-contour": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-array": "^3.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-delaunay": {
|
||||||
|
"version": "6.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
|
||||||
|
"integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==",
|
||||||
|
"dependencies": {
|
||||||
|
"delaunator": "5"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/d3-dispatch": {
|
"node_modules/d3-dispatch": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
|
||||||
|
|
@ -7765,6 +7833,38 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/d3-dsv": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"commander": "7",
|
||||||
|
"iconv-lite": "0.6",
|
||||||
|
"rw": "1"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"csv2json": "bin/dsv2json.js",
|
||||||
|
"csv2tsv": "bin/dsv2dsv.js",
|
||||||
|
"dsv2dsv": "bin/dsv2dsv.js",
|
||||||
|
"dsv2json": "bin/dsv2json.js",
|
||||||
|
"json2csv": "bin/json2dsv.js",
|
||||||
|
"json2dsv": "bin/json2dsv.js",
|
||||||
|
"json2tsv": "bin/json2dsv.js",
|
||||||
|
"tsv2csv": "bin/dsv2dsv.js",
|
||||||
|
"tsv2json": "bin/dsv2json.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-dsv/node_modules/commander": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/d3-ease": {
|
"node_modules/d3-ease": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
|
||||||
|
|
@ -7773,6 +7873,57 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/d3-fetch": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-dsv": "1 - 3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-force": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-dispatch": "1 - 3",
|
||||||
|
"d3-quadtree": "1 - 3",
|
||||||
|
"d3-timer": "1 - 3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-format": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-geo": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-array": "2.5.0 - 3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-hierarchy": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/d3-interpolate": {
|
"node_modules/d3-interpolate": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
|
||||||
|
|
@ -7784,6 +7935,65 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/d3-path": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-polygon": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-quadtree": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-random": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-scale": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-array": "2.10.0 - 3",
|
||||||
|
"d3-format": "1 - 3",
|
||||||
|
"d3-interpolate": "1.2.0 - 3",
|
||||||
|
"d3-time": "2.1.1 - 3",
|
||||||
|
"d3-time-format": "2 - 4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-scale-chromatic": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-color": "1 - 3",
|
||||||
|
"d3-interpolate": "1 - 3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/d3-selection": {
|
"node_modules/d3-selection": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
|
||||||
|
|
@ -7792,6 +8002,39 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/d3-shape": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-path": "^3.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-time": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-array": "2 - 3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/d3-time-format": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-time": "1 - 3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/d3-timer": {
|
"node_modules/d3-timer": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
|
||||||
|
|
@ -8022,6 +8265,14 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/delaunator": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==",
|
||||||
|
"dependencies": {
|
||||||
|
"robust-predicates": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/delayed-stream": {
|
"node_modules/delayed-stream": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
|
@ -11005,6 +11256,14 @@
|
||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/internmap": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/intl-messageformat": {
|
"node_modules/intl-messageformat": {
|
||||||
"version": "10.5.14",
|
"version": "10.5.14",
|
||||||
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.14.tgz",
|
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.14.tgz",
|
||||||
|
|
@ -17037,6 +17296,58 @@
|
||||||
"react-dom": "16 || 17 || 18"
|
"react-dom": "16 || 17 || 18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-gauge-chart": {
|
||||||
|
"version": "0.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-gauge-chart/-/react-gauge-chart-0.5.1.tgz",
|
||||||
|
"integrity": "sha512-Kd0pLIfHWOVEWJCz+xAxFfrKzCdOkLHNKR13V+O3h06ocyGT7fWjz2oevMXsPt3bVn1Du2od7gPrjUhqXKdASg==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3": "^7.6.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.8.2 || ^17.0 || ^18.x",
|
||||||
|
"react-dom": "^16.8.2 || ^17.0 || ^18.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-gauge-chart/node_modules/d3": {
|
||||||
|
"version": "7.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz",
|
||||||
|
"integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==",
|
||||||
|
"dependencies": {
|
||||||
|
"d3-array": "3",
|
||||||
|
"d3-axis": "3",
|
||||||
|
"d3-brush": "3",
|
||||||
|
"d3-chord": "3",
|
||||||
|
"d3-color": "3",
|
||||||
|
"d3-contour": "4",
|
||||||
|
"d3-delaunay": "6",
|
||||||
|
"d3-dispatch": "3",
|
||||||
|
"d3-drag": "3",
|
||||||
|
"d3-dsv": "3",
|
||||||
|
"d3-ease": "3",
|
||||||
|
"d3-fetch": "3",
|
||||||
|
"d3-force": "3",
|
||||||
|
"d3-format": "3",
|
||||||
|
"d3-geo": "3",
|
||||||
|
"d3-hierarchy": "3",
|
||||||
|
"d3-interpolate": "3",
|
||||||
|
"d3-path": "3",
|
||||||
|
"d3-polygon": "3",
|
||||||
|
"d3-quadtree": "3",
|
||||||
|
"d3-random": "3",
|
||||||
|
"d3-scale": "4",
|
||||||
|
"d3-scale-chromatic": "3",
|
||||||
|
"d3-selection": "3",
|
||||||
|
"d3-shape": "3",
|
||||||
|
"d3-time": "3",
|
||||||
|
"d3-time-format": "4",
|
||||||
|
"d3-timer": "3",
|
||||||
|
"d3-transition": "3",
|
||||||
|
"d3-zoom": "3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-helmet-async": {
|
"node_modules/react-helmet-async": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz",
|
||||||
|
|
@ -17652,6 +17963,11 @@
|
||||||
"url": "https://github.com/sponsors/isaacs"
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/robust-predicates": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg=="
|
||||||
|
},
|
||||||
"node_modules/rollup": {
|
"node_modules/rollup": {
|
||||||
"version": "2.79.1",
|
"version": "2.79.1",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
|
||||||
|
|
@ -17750,6 +18066,11 @@
|
||||||
"queue-microtask": "^1.2.2"
|
"queue-microtask": "^1.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/rw": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="
|
||||||
|
},
|
||||||
"node_modules/rxjs": {
|
"node_modules/rxjs": {
|
||||||
"version": "7.8.1",
|
"version": "7.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||||
|
|
@ -26418,11 +26739,60 @@
|
||||||
"resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz",
|
"resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz",
|
||||||
"integrity": "sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg=="
|
"integrity": "sha512-yFk/2idb8OHPKkbAL8QaOaqENNoMhIaSHZerk3oQsECwkObkCpJyjYwCe+OHiq6UEdhe1m8ZGARRRO3ljFjlKg=="
|
||||||
},
|
},
|
||||||
|
"d3-array": {
|
||||||
|
"version": "3.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
|
||||||
|
"integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
|
||||||
|
"requires": {
|
||||||
|
"internmap": "1 - 2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-axis": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw=="
|
||||||
|
},
|
||||||
|
"d3-brush": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==",
|
||||||
|
"requires": {
|
||||||
|
"d3-dispatch": "1 - 3",
|
||||||
|
"d3-drag": "2 - 3",
|
||||||
|
"d3-interpolate": "1 - 3",
|
||||||
|
"d3-selection": "3",
|
||||||
|
"d3-transition": "3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-chord": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==",
|
||||||
|
"requires": {
|
||||||
|
"d3-path": "1 - 3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"d3-color": {
|
"d3-color": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
|
||||||
"integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="
|
"integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="
|
||||||
},
|
},
|
||||||
|
"d3-contour": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "^3.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-delaunay": {
|
||||||
|
"version": "6.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
|
||||||
|
"integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==",
|
||||||
|
"requires": {
|
||||||
|
"delaunator": "5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"d3-dispatch": {
|
"d3-dispatch": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
|
||||||
|
|
@ -26437,11 +26807,64 @@
|
||||||
"d3-selection": "3"
|
"d3-selection": "3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"d3-dsv": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
|
||||||
|
"requires": {
|
||||||
|
"commander": "7",
|
||||||
|
"iconv-lite": "0.6",
|
||||||
|
"rw": "1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"commander": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"d3-ease": {
|
"d3-ease": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
|
||||||
"integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="
|
"integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="
|
||||||
},
|
},
|
||||||
|
"d3-fetch": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==",
|
||||||
|
"requires": {
|
||||||
|
"d3-dsv": "1 - 3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-force": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
|
||||||
|
"requires": {
|
||||||
|
"d3-dispatch": "1 - 3",
|
||||||
|
"d3-quadtree": "1 - 3",
|
||||||
|
"d3-timer": "1 - 3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-format": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA=="
|
||||||
|
},
|
||||||
|
"d3-geo": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "2.5.0 - 3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-hierarchy": {
|
||||||
|
"version": "3.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz",
|
||||||
|
"integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA=="
|
||||||
|
},
|
||||||
"d3-interpolate": {
|
"d3-interpolate": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
|
||||||
|
|
@ -26450,11 +26873,76 @@
|
||||||
"d3-color": "1 - 3"
|
"d3-color": "1 - 3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"d3-path": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="
|
||||||
|
},
|
||||||
|
"d3-polygon": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg=="
|
||||||
|
},
|
||||||
|
"d3-quadtree": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw=="
|
||||||
|
},
|
||||||
|
"d3-random": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ=="
|
||||||
|
},
|
||||||
|
"d3-scale": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "2.10.0 - 3",
|
||||||
|
"d3-format": "1 - 3",
|
||||||
|
"d3-interpolate": "1.2.0 - 3",
|
||||||
|
"d3-time": "2.1.1 - 3",
|
||||||
|
"d3-time-format": "2 - 4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-scale-chromatic": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==",
|
||||||
|
"requires": {
|
||||||
|
"d3-color": "1 - 3",
|
||||||
|
"d3-interpolate": "1 - 3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"d3-selection": {
|
"d3-selection": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
|
||||||
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ=="
|
"integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ=="
|
||||||
},
|
},
|
||||||
|
"d3-shape": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
|
||||||
|
"requires": {
|
||||||
|
"d3-path": "^3.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-time": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "2 - 3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"d3-time-format": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
|
||||||
|
"requires": {
|
||||||
|
"d3-time": "1 - 3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"d3-timer": {
|
"d3-timer": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
|
||||||
|
|
@ -26616,6 +27104,14 @@
|
||||||
"object-keys": "^1.1.1"
|
"object-keys": "^1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"delaunator": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==",
|
||||||
|
"requires": {
|
||||||
|
"robust-predicates": "^3.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"delayed-stream": {
|
"delayed-stream": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
|
@ -28819,6 +29315,11 @@
|
||||||
"side-channel": "^1.0.4"
|
"side-channel": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"internmap": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="
|
||||||
|
},
|
||||||
"intl-messageformat": {
|
"intl-messageformat": {
|
||||||
"version": "10.5.14",
|
"version": "10.5.14",
|
||||||
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.14.tgz",
|
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.14.tgz",
|
||||||
|
|
@ -33141,6 +33642,53 @@
|
||||||
"zustand": "^3.7.2"
|
"zustand": "^3.7.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-gauge-chart": {
|
||||||
|
"version": "0.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-gauge-chart/-/react-gauge-chart-0.5.1.tgz",
|
||||||
|
"integrity": "sha512-Kd0pLIfHWOVEWJCz+xAxFfrKzCdOkLHNKR13V+O3h06ocyGT7fWjz2oevMXsPt3bVn1Du2od7gPrjUhqXKdASg==",
|
||||||
|
"requires": {
|
||||||
|
"d3": "^7.6.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"d3": {
|
||||||
|
"version": "7.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz",
|
||||||
|
"integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==",
|
||||||
|
"requires": {
|
||||||
|
"d3-array": "3",
|
||||||
|
"d3-axis": "3",
|
||||||
|
"d3-brush": "3",
|
||||||
|
"d3-chord": "3",
|
||||||
|
"d3-color": "3",
|
||||||
|
"d3-contour": "4",
|
||||||
|
"d3-delaunay": "6",
|
||||||
|
"d3-dispatch": "3",
|
||||||
|
"d3-drag": "3",
|
||||||
|
"d3-dsv": "3",
|
||||||
|
"d3-ease": "3",
|
||||||
|
"d3-fetch": "3",
|
||||||
|
"d3-force": "3",
|
||||||
|
"d3-format": "3",
|
||||||
|
"d3-geo": "3",
|
||||||
|
"d3-hierarchy": "3",
|
||||||
|
"d3-interpolate": "3",
|
||||||
|
"d3-path": "3",
|
||||||
|
"d3-polygon": "3",
|
||||||
|
"d3-quadtree": "3",
|
||||||
|
"d3-random": "3",
|
||||||
|
"d3-scale": "4",
|
||||||
|
"d3-scale-chromatic": "3",
|
||||||
|
"d3-selection": "3",
|
||||||
|
"d3-shape": "3",
|
||||||
|
"d3-time": "3",
|
||||||
|
"d3-time-format": "4",
|
||||||
|
"d3-timer": "3",
|
||||||
|
"d3-transition": "3",
|
||||||
|
"d3-zoom": "3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-helmet-async": {
|
"react-helmet-async": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz",
|
||||||
|
|
@ -33586,6 +34134,11 @@
|
||||||
"glob": "^7.1.3"
|
"glob": "^7.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"robust-predicates": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg=="
|
||||||
|
},
|
||||||
"rollup": {
|
"rollup": {
|
||||||
"version": "2.79.1",
|
"version": "2.79.1",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
|
||||||
|
|
@ -33653,6 +34206,11 @@
|
||||||
"queue-microtask": "^1.2.2"
|
"queue-microtask": "^1.2.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"rw": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
|
||||||
|
"integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="
|
||||||
|
},
|
||||||
"rxjs": {
|
"rxjs": {
|
||||||
"version": "7.8.1",
|
"version": "7.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
"axios": "^1.5.0",
|
"axios": "^1.5.0",
|
||||||
"chart.js": "^4.4.0",
|
"chart.js": "^4.4.0",
|
||||||
"clsx": "1.1.1",
|
"clsx": "1.1.1",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
"cytoscape": "^3.26.0",
|
"cytoscape": "^3.26.0",
|
||||||
"date-fns": "^2.28.0",
|
"date-fns": "^2.28.0",
|
||||||
"dayjs": "^1.11.10",
|
"dayjs": "^1.11.10",
|
||||||
|
|
@ -32,6 +33,7 @@
|
||||||
"react-cytoscapejs": "^2.0.0",
|
"react-cytoscapejs": "^2.0.0",
|
||||||
"react-dom": "17.0.2",
|
"react-dom": "17.0.2",
|
||||||
"react-flow-renderer": "^10.3.17",
|
"react-flow-renderer": "^10.3.17",
|
||||||
|
"react-gauge-chart": "^0.5.1",
|
||||||
"react-helmet-async": "1.3.0",
|
"react-helmet-async": "1.3.0",
|
||||||
"react-icons": "^4.11.0",
|
"react-icons": "^4.11.0",
|
||||||
"react-icons-converter": "^1.1.4",
|
"react-icons-converter": "^1.1.4",
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,5 @@
|
||||||
|
|
||||||
.apexcharts-toolbar {
|
.apexcharts-toolbar {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import CircularProgress from '@mui/material/CircularProgress';
|
||||||
import MainStats from './MainStats';
|
import MainStats from './MainStats';
|
||||||
import DetailedBatteryView from './DetailedBatteryView';
|
import DetailedBatteryView from './DetailedBatteryView';
|
||||||
import { ProductIdContext } from '../../../contexts/ProductIdContextProvider';
|
import { ProductIdContext } from '../../../contexts/ProductIdContextProvider';
|
||||||
|
import DetailedBatteryViewSodistore from './DetailedBatteryViewSodistore';
|
||||||
|
|
||||||
interface BatteryViewProps {
|
interface BatteryViewProps {
|
||||||
values: JSONRecordData;
|
values: JSONRecordData;
|
||||||
|
|
@ -175,23 +176,41 @@ function BatteryView(props: BatteryViewProps) {
|
||||||
></MainStats>
|
></MainStats>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{Object.entries(props.values.Battery.Devices).map(
|
{product === 0
|
||||||
([BatteryId, battery]) => (
|
? Object.entries(props.values.Battery.Devices).map(
|
||||||
<Route
|
([BatteryId, battery]) => (
|
||||||
key={routes.detailed_view + BatteryId}
|
<Route
|
||||||
path={routes.detailed_view + BatteryId}
|
key={routes.detailed_view + BatteryId}
|
||||||
element={
|
path={routes.detailed_view + BatteryId}
|
||||||
<DetailedBatteryView
|
element={
|
||||||
batteryId={Number(BatteryId)}
|
<DetailedBatteryView
|
||||||
s3Credentials={props.s3Credentials}
|
batteryId={Number(BatteryId)}
|
||||||
batteryData={battery}
|
s3Credentials={props.s3Credentials}
|
||||||
installationId={props.installationId}
|
batteryData={battery}
|
||||||
productNum={product}
|
installationId={props.installationId}
|
||||||
></DetailedBatteryView>
|
productNum={product}
|
||||||
}
|
></DetailedBatteryView>
|
||||||
/>
|
}
|
||||||
)
|
/>
|
||||||
)}
|
)
|
||||||
|
)
|
||||||
|
: Object.entries(props.values.Battery.Devices).map(
|
||||||
|
([BatteryId, battery]) => (
|
||||||
|
<Route
|
||||||
|
key={routes.detailed_view + BatteryId}
|
||||||
|
path={routes.detailed_view + BatteryId}
|
||||||
|
element={
|
||||||
|
<DetailedBatteryViewSodistore
|
||||||
|
batteryId={Number(BatteryId)}
|
||||||
|
s3Credentials={props.s3Credentials}
|
||||||
|
batteryData={battery}
|
||||||
|
installationId={props.installationId}
|
||||||
|
productNum={product}
|
||||||
|
></DetailedBatteryViewSodistore>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
)}
|
||||||
</Routes>
|
</Routes>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|
@ -226,6 +245,9 @@ function BatteryView(props: BatteryViewProps) {
|
||||||
) : (
|
) : (
|
||||||
<TableCell align="center">Max Cell Voltage</TableCell>
|
<TableCell align="center">Max Cell Voltage</TableCell>
|
||||||
)}
|
)}
|
||||||
|
{product === 3 && (
|
||||||
|
<TableCell align="center">Voltage Difference</TableCell>
|
||||||
|
)}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
|
|
@ -350,14 +372,21 @@ function BatteryView(props: BatteryViewProps) {
|
||||||
: '#32CD32'
|
: '#32CD32'
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
const avgTemp =
|
||||||
|
(battery.BatteryDeligreenDataRecord.TemperaturesList
|
||||||
|
.CellTemperature1 +
|
||||||
|
battery.BatteryDeligreenDataRecord
|
||||||
|
.TemperaturesList.CellTemperature2 +
|
||||||
|
battery.BatteryDeligreenDataRecord
|
||||||
|
.TemperaturesList.CellTemperature3 +
|
||||||
|
battery.BatteryDeligreenDataRecord
|
||||||
|
.TemperaturesList.CellTemperature4) /
|
||||||
|
4;
|
||||||
return {
|
return {
|
||||||
width: '10%',
|
width: '10%',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
battery.BatteryDeligreenDataRecord
|
avgTemp > 50 || avgTemp < 0
|
||||||
.TemperaturesList.EnvironmentTemperature > 50 ||
|
|
||||||
battery.BatteryDeligreenDataRecord
|
|
||||||
.TemperaturesList.EnvironmentTemperature < 0
|
|
||||||
? '#FF033E'
|
? '#FF033E'
|
||||||
: '#32CD32'
|
: '#32CD32'
|
||||||
};
|
};
|
||||||
|
|
@ -459,13 +488,13 @@ function BatteryView(props: BatteryViewProps) {
|
||||||
<>
|
<>
|
||||||
<TableCell
|
<TableCell
|
||||||
sx={{
|
sx={{
|
||||||
width: '20%',
|
width: '15%',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
padding: '8px',
|
padding: '8px',
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
minVoltage < 1.82 || minVoltage > 3.94
|
minVoltage < 2
|
||||||
? '#FF033E'
|
? '#FF033E'
|
||||||
: minVoltage < 2 || minVoltage > 3.8
|
: minVoltage > 2 && minVoltage < 2.2
|
||||||
? '#ffbf00'
|
? '#ffbf00'
|
||||||
: '#32CD32',
|
: '#32CD32',
|
||||||
color: minVoltage != 0 ? 'black' : 'white'
|
color: minVoltage != 0 ? 'black' : 'white'
|
||||||
|
|
@ -476,13 +505,13 @@ function BatteryView(props: BatteryViewProps) {
|
||||||
|
|
||||||
<TableCell
|
<TableCell
|
||||||
sx={{
|
sx={{
|
||||||
width: '20%',
|
width: '15%',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
padding: '8px',
|
padding: '8px',
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
maxVoltage < 1.82 || maxVoltage > 3.94
|
maxVoltage > 3.9
|
||||||
? '#FF033E'
|
? '#FF033E'
|
||||||
: maxVoltage < 2 || maxVoltage > 3.8
|
: maxVoltage < 3.9 && maxVoltage > 3.8
|
||||||
? '#ffbf00'
|
? '#ffbf00'
|
||||||
: '#32CD32',
|
: '#32CD32',
|
||||||
color: maxVoltage != 0 ? 'black' : 'white'
|
color: maxVoltage != 0 ? 'black' : 'white'
|
||||||
|
|
@ -495,6 +524,46 @@ function BatteryView(props: BatteryViewProps) {
|
||||||
})()}
|
})()}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
{product === 3 && (
|
||||||
|
<>
|
||||||
|
{(() => {
|
||||||
|
const cellVoltagesString =
|
||||||
|
battery.BatteryDeligreenDataRecord.CellVoltage ||
|
||||||
|
'';
|
||||||
|
|
||||||
|
const cellVoltagesArray: number[] = cellVoltagesString
|
||||||
|
.split(',')
|
||||||
|
.map((v) => parseFloat(v.trim()))
|
||||||
|
.filter((v) => !isNaN(v)); // Filter invalid numbers
|
||||||
|
|
||||||
|
const minVoltage = Math.min(...cellVoltagesArray);
|
||||||
|
const maxVoltage = Math.max(...cellVoltagesArray);
|
||||||
|
|
||||||
|
const voltage_diff = maxVoltage - minVoltage;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<TableCell
|
||||||
|
sx={{
|
||||||
|
width: '15%',
|
||||||
|
textAlign: 'center',
|
||||||
|
padding: '8px',
|
||||||
|
backgroundColor:
|
||||||
|
voltage_diff > 0.2
|
||||||
|
? '#FF033E'
|
||||||
|
: voltage_diff > 0.1 && voltage_diff < 0.2
|
||||||
|
? '#ffbf00'
|
||||||
|
: '#32CD32',
|
||||||
|
color: voltage_diff != 0 ? 'black' : 'white'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{voltage_diff.toFixed(3)} V{' '}
|
||||||
|
</TableCell>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -135,6 +135,8 @@ function MainStats(props: MainStatsProps) {
|
||||||
function generateSeries(chartData, category, color) {
|
function generateSeries(chartData, category, color) {
|
||||||
const series = [];
|
const series = [];
|
||||||
const pathsToSearch = [
|
const pathsToSearch = [
|
||||||
|
'Node0',
|
||||||
|
'Node1',
|
||||||
'Node2',
|
'Node2',
|
||||||
'Node3',
|
'Node3',
|
||||||
'Node4',
|
'Node4',
|
||||||
|
|
@ -143,8 +145,7 @@ function MainStats(props: MainStatsProps) {
|
||||||
'Node7',
|
'Node7',
|
||||||
'Node8',
|
'Node8',
|
||||||
'Node9',
|
'Node9',
|
||||||
'Node10',
|
'Node10'
|
||||||
'Node11'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,113 @@ export interface Device {
|
||||||
TotalBatteryVoltage: number;
|
TotalBatteryVoltage: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BatteryDeligreenAlarmRecord: {
|
||||||
|
OnOffState: {
|
||||||
|
ChargeSwitchState: string;
|
||||||
|
CurrentLimitSwitchStat: string;
|
||||||
|
DischargeSwitchState: string;
|
||||||
|
HeatingSwitchState: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
AlarmEvent1: {
|
||||||
|
CellVoltageDropoutFault: string;
|
||||||
|
ChargeSwitchFault: string;
|
||||||
|
CurrentLimitSwitchFault: string;
|
||||||
|
CurrentSensorFault: string;
|
||||||
|
DischargeSwitchFault: string;
|
||||||
|
KeySwitchFault: string;
|
||||||
|
TemperatureSensorFault: string;
|
||||||
|
VoltageSensorFault: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
AlarmEvent2: {
|
||||||
|
HighVoltageAlarmForTotalVoltage: string;
|
||||||
|
LowVoltageAlarmForTotalVoltage: string;
|
||||||
|
MonomerHighVoltageAlarm: string;
|
||||||
|
MonomerLowVoltageAlarm: string;
|
||||||
|
MonomerOvervoltageProtection: string;
|
||||||
|
MonomerUnderVoltageProtection: string;
|
||||||
|
OvervoltageProtectionForTotalVoltage: string;
|
||||||
|
UnderVoltageProtectionForTotalVoltage: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
AlarmEvent3: {
|
||||||
|
ChargeHighTemperatureAlarm: string;
|
||||||
|
ChargeLowTemperatureAlarm: string;
|
||||||
|
ChargeOverTemperatureProtection: string;
|
||||||
|
ChargeUnderTemperatureProtection: string;
|
||||||
|
DischargeHighTemperatureAlarm: string;
|
||||||
|
DischargeLowTemperatureAlarm: string;
|
||||||
|
DischargeOverTemperatureProtection: string;
|
||||||
|
DischargeUnderTemperatureProtection: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
AlarmEvent4: {
|
||||||
|
CellLowTemperatureHeating: string;
|
||||||
|
EnvironmentHighTemperatureAlarm: string;
|
||||||
|
EnvironmentLowTemperatureAlarm: string;
|
||||||
|
EnvironmentOverTemperatureProtection: string;
|
||||||
|
EnvironmentUnderTemperatureProtection: string;
|
||||||
|
PowerHighTemperatureAlarm: string;
|
||||||
|
PowerOverTemperatureProtection: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
AlarmEvent5: {
|
||||||
|
ChargeOverCurrentAlarm: string;
|
||||||
|
ChargeOverCurrentProtection: string;
|
||||||
|
DischargeOverCurrentAlarm: string;
|
||||||
|
DischargeOverCurrentProtection: string;
|
||||||
|
OutputShortCircuitLockout: string;
|
||||||
|
OutputShortCircuitProtection: string;
|
||||||
|
TransientOverCurrentLockout: string;
|
||||||
|
TransientOverCurrentProtection: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
AlarmEvent6: {
|
||||||
|
CellLowVoltageChargingProhibition: string;
|
||||||
|
ChargeHighVoltageProtection: string;
|
||||||
|
InsideBit: string;
|
||||||
|
IntermittentRechargeWaiting: string;
|
||||||
|
OutputConnectionFault: string;
|
||||||
|
OutputReversePolarityProtection: string;
|
||||||
|
ResidualCapacityAlarm: string;
|
||||||
|
ResidualCapacityProtection: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
AlarmEvent7: {
|
||||||
|
AutomaticChargingWaiting: string;
|
||||||
|
InsideBit1: string;
|
||||||
|
InsideBit2: string;
|
||||||
|
InsideBit3: string;
|
||||||
|
InsideBit4: string;
|
||||||
|
InsideBit5: string;
|
||||||
|
InsideBit6: string;
|
||||||
|
ManualChargingWaiting: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
AlarmEvent8: {
|
||||||
|
CurrentCalibrationNotPerformed: string;
|
||||||
|
EepStorageFault: string;
|
||||||
|
InsideBit1: string;
|
||||||
|
InsideBit2: string;
|
||||||
|
InsideBit3: string;
|
||||||
|
RtcError: string;
|
||||||
|
VoltageCalibrationNotPerformed: string;
|
||||||
|
ZeroCalibrationNotPerformed: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
CellAlarmList: string;
|
||||||
|
CellTemperatureAlarm: string;
|
||||||
|
|
||||||
|
SystemState: {
|
||||||
|
Charge: string;
|
||||||
|
Discharge: string;
|
||||||
|
FloatingCharge: string;
|
||||||
|
Shutdown: string;
|
||||||
|
Standby: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
Leds: Leds;
|
Leds: Leds;
|
||||||
Eoc: boolean;
|
Eoc: boolean;
|
||||||
Soc: number;
|
Soc: number;
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,7 @@ export const transformInputToBatteryViewDataJson = async (
|
||||||
);
|
);
|
||||||
|
|
||||||
const adjustedTimestamp =
|
const adjustedTimestamp =
|
||||||
product == 0
|
product == 0 || product == 3
|
||||||
? new Date(timestampArray[i] * 1000)
|
? new Date(timestampArray[i] * 1000)
|
||||||
: new Date(timestampArray[i] * 100000);
|
: new Date(timestampArray[i] * 100000);
|
||||||
//Timezone offset is negative, so we convert the timestamp to the current zone by subtracting the corresponding offset
|
//Timezone offset is negative, so we convert the timestamp to the current zone by subtracting the corresponding offset
|
||||||
|
|
@ -185,19 +185,21 @@ export const transformInputToBatteryViewDataJson = async (
|
||||||
const battery_nodes =
|
const battery_nodes =
|
||||||
result.Config.Devices.BatteryNodes.toString().split(',');
|
result.Config.Devices.BatteryNodes.toString().split(',');
|
||||||
|
|
||||||
// console.log(battery_nodes);
|
|
||||||
|
|
||||||
//Initialize the chartData structure based on the node names extracted from the first result
|
//Initialize the chartData structure based on the node names extracted from the first result
|
||||||
let old_length = pathsToSave.length;
|
let old_length = pathsToSave.length;
|
||||||
|
|
||||||
if (battery_nodes.length > old_length) {
|
if (battery_nodes.length > old_length) {
|
||||||
battery_nodes.forEach((node) => {
|
battery_nodes.forEach((node) => {
|
||||||
if (!pathsToSave.includes('Node' + node)) {
|
const node_number =
|
||||||
pathsToSave.push('Node' + node);
|
product == 3 ? Number(node) + 1 : Number(node) - 1;
|
||||||
|
if (!pathsToSave.includes('Node' + node_number)) {
|
||||||
|
pathsToSave.push('Node' + node_number);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// console.log(pathsToSave);
|
||||||
|
|
||||||
if (initialiation) {
|
if (initialiation) {
|
||||||
initialiation = false;
|
initialiation = false;
|
||||||
categories.forEach((category) => {
|
categories.forEach((category) => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue