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 InnovEnergy.App.Backend.Database;
|
||||
using InnovEnergy.App.Backend.Websockets;
|
||||
using InnovEnergy.App.Backend.DeleteOldData;
|
||||
using Microsoft.AspNetCore.HttpOverrides;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.OpenApi.Models;
|
||||
|
|
@ -31,6 +32,9 @@ public static class Program
|
|||
WebsocketManager.MonitorSalidomoInstallationTable().SupressAwaitWarning();
|
||||
WebsocketManager.MonitorSodistoreInstallationTable().SupressAwaitWarning();
|
||||
|
||||
|
||||
Task.Run(() => DeleteOldDataFromS3.DeleteOldData());
|
||||
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddProblemDetails(setup =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ public static class WebsocketManager
|
|||
{
|
||||
while (true){
|
||||
lock (InstallationConnections){
|
||||
Console.WriteLine("MONITOR SALIMAX INSTALLATIONS\n");
|
||||
// Console.WriteLine("MONITOR SALIMAX INSTALLATIONS\n");
|
||||
foreach (var installationConnection in InstallationConnections){
|
||||
|
||||
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);}
|
||||
}
|
||||
}
|
||||
Console.WriteLine("FINISHED MONITORING SALIMAX INSTALLATIONS\n");
|
||||
// Console.WriteLine("FINISHED MONITORING SALIMAX INSTALLATIONS\n");
|
||||
}
|
||||
|
||||
await Task.Delay(TimeSpan.FromMinutes(1));
|
||||
|
|
@ -47,15 +47,15 @@ public static class WebsocketManager
|
|||
public static async Task MonitorSalidomoInstallationTable()
|
||||
{
|
||||
while (true){
|
||||
Console.WriteLine("TRY TO LOCK FOR MONITOR SALIDOMO INSTALLATIONS\n");
|
||||
//Console.WriteLine("TRY TO LOCK FOR MONITOR SALIDOMO INSTALLATIONS\n");
|
||||
lock (InstallationConnections){
|
||||
Console.WriteLine("MONITOR SALIDOMO INSTALLATIONS\n");
|
||||
//Console.WriteLine("MONITOR SALIDOMO INSTALLATIONS\n");
|
||||
foreach (var installationConnection in InstallationConnections)
|
||||
{
|
||||
//Console.WriteLine("Installation ID is "+installationConnection.Key);
|
||||
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));
|
||||
}
|
||||
// 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));
|
||||
// }
|
||||
|
||||
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));
|
||||
|
||||
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.Apply(Db.Update);
|
||||
|
||||
installationConnection.Value.Status = (int)StatusType.Offline;
|
||||
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));
|
||||
}
|
||||
|
|
@ -84,9 +84,9 @@ public static class WebsocketManager
|
|||
public static async Task MonitorSodistoreInstallationTable()
|
||||
{
|
||||
while (true){
|
||||
Console.WriteLine("TRY TO LOCK FOR MONITOR SODISTORE INSTALLATIONS\n");
|
||||
//Console.WriteLine("TRY TO LOCK FOR MONITOR SODISTORE INSTALLATIONS\n");
|
||||
lock (InstallationConnections){
|
||||
Console.WriteLine("MONITOR SODISTORE INSTALLATIONS\n");
|
||||
//Console.WriteLine("MONITOR SODISTORE INSTALLATIONS\n");
|
||||
foreach (var installationConnection in InstallationConnections)
|
||||
{
|
||||
|
||||
|
|
@ -97,16 +97,16 @@ public static class WebsocketManager
|
|||
//Console.WriteLine("timestamp now is is "+(DateTime.Now));
|
||||
|
||||
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.Apply(Db.Update);
|
||||
|
||||
installationConnection.Value.Status = (int)StatusType.Offline;
|
||||
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));
|
||||
}
|
||||
|
|
@ -225,20 +225,20 @@ public static class WebsocketManager
|
|||
);
|
||||
|
||||
|
||||
Console.WriteLine("Printing installation connection list");
|
||||
Console.WriteLine("----------------------------------------------");
|
||||
foreach (var installationConnection in InstallationConnections)
|
||||
{
|
||||
Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count);
|
||||
}
|
||||
Console.WriteLine("----------------------------------------------");
|
||||
// Console.WriteLine("Printing installation connection list");
|
||||
// Console.WriteLine("----------------------------------------------");
|
||||
// foreach (var installationConnection in InstallationConnections)
|
||||
// {
|
||||
// Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count);
|
||||
// }
|
||||
// Console.WriteLine("----------------------------------------------");
|
||||
}
|
||||
}
|
||||
|
||||
lock (InstallationConnections)
|
||||
{
|
||||
//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)
|
||||
{
|
||||
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);
|
||||
lock (InstallationConnections)
|
||||
{
|
||||
//Print the installationConnections dictionary after deleting a websocket
|
||||
Console.WriteLine("Print the installation connections list after deleting a websocket");
|
||||
Console.WriteLine("----------------------------------------------");
|
||||
foreach (var installationConnection in InstallationConnections)
|
||||
{
|
||||
Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count);
|
||||
}
|
||||
|
||||
Console.WriteLine("----------------------------------------------");
|
||||
}
|
||||
// lock (InstallationConnections)
|
||||
// {
|
||||
// //Print the installationConnections dictionary after deleting a websocket
|
||||
// Console.WriteLine("Print the installation connections list after deleting a websocket");
|
||||
// Console.WriteLine("----------------------------------------------");
|
||||
// foreach (var installationConnection in InstallationConnections)
|
||||
// {
|
||||
// Console.WriteLine("Installation ID: " + installationConnection.Key + " Number of Connections: " + installationConnection.Value.Connections.Count);
|
||||
// }
|
||||
//
|
||||
// Console.WriteLine("----------------------------------------------");
|
||||
// }
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
"react-cytoscapejs": "^2.0.0",
|
||||
"react-dom": "17.0.2",
|
||||
"react-flow-renderer": "^10.3.17",
|
||||
"react-gauge-chart": "^0.5.1",
|
||||
"react-helmet-async": "1.3.0",
|
||||
"react-icons": "^4.11.0",
|
||||
"react-icons-converter": "^1.1.4",
|
||||
|
|
@ -7737,6 +7738,51 @@
|
|||
"resolved": "https://registry.npmjs.org/d3/-/d3-3.5.17.tgz",
|
||||
"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": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
|
||||
|
|
@ -7745,6 +7791,28 @@
|
|||
"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": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
|
||||
|
|
@ -7765,6 +7833,38 @@
|
|||
"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": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
|
||||
|
|
@ -7773,6 +7873,57 @@
|
|||
"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": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
|
||||
|
|
@ -7784,6 +7935,65 @@
|
|||
"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": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
|
||||
|
|
@ -7792,6 +8002,39 @@
|
|||
"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": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
|
||||
|
|
@ -8022,6 +8265,14 @@
|
|||
"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": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
|
|
@ -11005,6 +11256,14 @@
|
|||
"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": {
|
||||
"version": "10.5.14",
|
||||
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.14.tgz",
|
||||
|
|
@ -17037,6 +17296,58 @@
|
|||
"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": {
|
||||
"version": "1.3.0",
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"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": {
|
||||
"version": "2.79.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
|
||||
|
|
@ -17750,6 +18066,11 @@
|
|||
"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": {
|
||||
"version": "7.8.1",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
|
||||
"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": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
|
||||
|
|
@ -26437,11 +26807,64 @@
|
|||
"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": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
|
||||
"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": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
|
||||
|
|
@ -26450,11 +26873,76 @@
|
|||
"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": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
|
||||
"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": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
|
||||
|
|
@ -26616,6 +27104,14 @@
|
|||
"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": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
|
|
@ -28819,6 +29315,11 @@
|
|||
"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": {
|
||||
"version": "10.5.14",
|
||||
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.5.14.tgz",
|
||||
|
|
@ -33141,6 +33642,53 @@
|
|||
"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": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz",
|
||||
|
|
@ -33586,6 +34134,11 @@
|
|||
"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": {
|
||||
"version": "2.79.1",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
|
||||
|
|
@ -33653,6 +34206,11 @@
|
|||
"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": {
|
||||
"version": "7.8.1",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
"axios": "^1.5.0",
|
||||
"chart.js": "^4.4.0",
|
||||
"clsx": "1.1.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"cytoscape": "^3.26.0",
|
||||
"date-fns": "^2.28.0",
|
||||
"dayjs": "^1.11.10",
|
||||
|
|
@ -32,6 +33,7 @@
|
|||
"react-cytoscapejs": "^2.0.0",
|
||||
"react-dom": "17.0.2",
|
||||
"react-flow-renderer": "^10.3.17",
|
||||
"react-gauge-chart": "^0.5.1",
|
||||
"react-helmet-async": "1.3.0",
|
||||
"react-icons": "^4.11.0",
|
||||
"react-icons-converter": "^1.1.4",
|
||||
|
|
|
|||
|
|
@ -7,3 +7,4 @@
|
|||
.apexcharts-toolbar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import CircularProgress from '@mui/material/CircularProgress';
|
|||
import MainStats from './MainStats';
|
||||
import DetailedBatteryView from './DetailedBatteryView';
|
||||
import { ProductIdContext } from '../../../contexts/ProductIdContextProvider';
|
||||
import DetailedBatteryViewSodistore from './DetailedBatteryViewSodistore';
|
||||
|
||||
interface BatteryViewProps {
|
||||
values: JSONRecordData;
|
||||
|
|
@ -175,7 +176,8 @@ function BatteryView(props: BatteryViewProps) {
|
|||
></MainStats>
|
||||
}
|
||||
/>
|
||||
{Object.entries(props.values.Battery.Devices).map(
|
||||
{product === 0
|
||||
? Object.entries(props.values.Battery.Devices).map(
|
||||
([BatteryId, battery]) => (
|
||||
<Route
|
||||
key={routes.detailed_view + BatteryId}
|
||||
|
|
@ -191,6 +193,23 @@ function BatteryView(props: BatteryViewProps) {
|
|||
}
|
||||
/>
|
||||
)
|
||||
)
|
||||
: 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>
|
||||
</Grid>
|
||||
|
|
@ -226,6 +245,9 @@ function BatteryView(props: BatteryViewProps) {
|
|||
) : (
|
||||
<TableCell align="center">Max Cell Voltage</TableCell>
|
||||
)}
|
||||
{product === 3 && (
|
||||
<TableCell align="center">Voltage Difference</TableCell>
|
||||
)}
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
|
|
@ -350,14 +372,21 @@ function BatteryView(props: BatteryViewProps) {
|
|||
: '#32CD32'
|
||||
};
|
||||
} else {
|
||||
const avgTemp =
|
||||
(battery.BatteryDeligreenDataRecord.TemperaturesList
|
||||
.CellTemperature1 +
|
||||
battery.BatteryDeligreenDataRecord
|
||||
.TemperaturesList.CellTemperature2 +
|
||||
battery.BatteryDeligreenDataRecord
|
||||
.TemperaturesList.CellTemperature3 +
|
||||
battery.BatteryDeligreenDataRecord
|
||||
.TemperaturesList.CellTemperature4) /
|
||||
4;
|
||||
return {
|
||||
width: '10%',
|
||||
textAlign: 'center',
|
||||
backgroundColor:
|
||||
battery.BatteryDeligreenDataRecord
|
||||
.TemperaturesList.EnvironmentTemperature > 50 ||
|
||||
battery.BatteryDeligreenDataRecord
|
||||
.TemperaturesList.EnvironmentTemperature < 0
|
||||
avgTemp > 50 || avgTemp < 0
|
||||
? '#FF033E'
|
||||
: '#32CD32'
|
||||
};
|
||||
|
|
@ -459,13 +488,13 @@ function BatteryView(props: BatteryViewProps) {
|
|||
<>
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '20%',
|
||||
width: '15%',
|
||||
textAlign: 'center',
|
||||
padding: '8px',
|
||||
backgroundColor:
|
||||
minVoltage < 1.82 || minVoltage > 3.94
|
||||
minVoltage < 2
|
||||
? '#FF033E'
|
||||
: minVoltage < 2 || minVoltage > 3.8
|
||||
: minVoltage > 2 && minVoltage < 2.2
|
||||
? '#ffbf00'
|
||||
: '#32CD32',
|
||||
color: minVoltage != 0 ? 'black' : 'white'
|
||||
|
|
@ -476,13 +505,13 @@ function BatteryView(props: BatteryViewProps) {
|
|||
|
||||
<TableCell
|
||||
sx={{
|
||||
width: '20%',
|
||||
width: '15%',
|
||||
textAlign: 'center',
|
||||
padding: '8px',
|
||||
backgroundColor:
|
||||
maxVoltage < 1.82 || maxVoltage > 3.94
|
||||
maxVoltage > 3.9
|
||||
? '#FF033E'
|
||||
: maxVoltage < 2 || maxVoltage > 3.8
|
||||
: maxVoltage < 3.9 && maxVoltage > 3.8
|
||||
? '#ffbf00'
|
||||
: '#32CD32',
|
||||
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>
|
||||
))}
|
||||
</TableBody>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -135,6 +135,8 @@ function MainStats(props: MainStatsProps) {
|
|||
function generateSeries(chartData, category, color) {
|
||||
const series = [];
|
||||
const pathsToSearch = [
|
||||
'Node0',
|
||||
'Node1',
|
||||
'Node2',
|
||||
'Node3',
|
||||
'Node4',
|
||||
|
|
@ -143,8 +145,7 @@ function MainStats(props: MainStatsProps) {
|
|||
'Node7',
|
||||
'Node8',
|
||||
'Node9',
|
||||
'Node10',
|
||||
'Node11'
|
||||
'Node10'
|
||||
];
|
||||
|
||||
let i = 0;
|
||||
|
|
|
|||
|
|
@ -68,6 +68,113 @@ export interface Device {
|
|||
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;
|
||||
Eoc: boolean;
|
||||
Soc: number;
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ export const transformInputToBatteryViewDataJson = async (
|
|||
);
|
||||
|
||||
const adjustedTimestamp =
|
||||
product == 0
|
||||
product == 0 || product == 3
|
||||
? new Date(timestampArray[i] * 1000)
|
||||
: new Date(timestampArray[i] * 100000);
|
||||
//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 =
|
||||
result.Config.Devices.BatteryNodes.toString().split(',');
|
||||
|
||||
// console.log(battery_nodes);
|
||||
|
||||
//Initialize the chartData structure based on the node names extracted from the first result
|
||||
let old_length = pathsToSave.length;
|
||||
|
||||
if (battery_nodes.length > old_length) {
|
||||
battery_nodes.forEach((node) => {
|
||||
if (!pathsToSave.includes('Node' + node)) {
|
||||
pathsToSave.push('Node' + node);
|
||||
const node_number =
|
||||
product == 3 ? Number(node) + 1 : Number(node) - 1;
|
||||
if (!pathsToSave.includes('Node' + node_number)) {
|
||||
pathsToSave.push('Node' + node_number);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// console.log(pathsToSave);
|
||||
|
||||
if (initialiation) {
|
||||
initialiation = false;
|
||||
categories.forEach((category) => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue