forked from RnD/rotatingMachine
All KPIs added
This commit is contained in:
48
README.md
48
README.md
@@ -4,20 +4,64 @@ Mean Time Between Failures: MTBF is a key indicator of asset reliability. It rep
|
|||||||
- Formula: MTBF = runtime / failures
|
- Formula: MTBF = runtime / failures
|
||||||
|
|
||||||
Mean Time to Repair: MTTR focuses on the speed of failure recovery. It indicates how long it takes on average to repair a failure and restore the system to operational condition. The lower the value, the better.
|
Mean Time to Repair: MTTR focuses on the speed of failure recovery. It indicates how long it takes on average to repair a failure and restore the system to operational condition. The lower the value, the better.
|
||||||
- Formula: MTTR = downtime / failures
|
- Formula: MTTR = maintenance_time / failures
|
||||||
|
|
||||||
Asset Availability: Asset availability indicates how often machines are available for use. Higher availability means that the equipment experiences fewer breakdowns and remains operational for a greater amount of time.
|
Asset Availability: Asset availability indicates how often machines are available for use. Higher availability means that the equipment experiences fewer breakdowns and remains operational for a greater amount of time.
|
||||||
- Formula: availability = MTBF / (MTBF + MTTR) * 100%
|
- Formula: availability = MTBF / (MTBF + MTTR) * 100%
|
||||||
|
|
||||||
Asset Health Index: A score ranging from 0 (optimal condition) to 5 (worst case) that reflects the overall health status of an asset.
|
Asset Health Index: A score ranging from 0 (optimal condition) to 5 (worst case) that reflects the overall health status of an asset.
|
||||||
|
How Asset Health Index is being calculated:
|
||||||
|
1. Hard rule first: If the machine state is "maintenance", the health index is set straight to 5 (worst).
|
||||||
|
|
||||||
|
2. Otherwise it uses 3 inputs:
|
||||||
|
Unavailability = 1 - availability
|
||||||
|
If the machine is often down (low availability), this gets higher → worse health.
|
||||||
|
|
||||||
|
Drift score = how much measured vs. predicted pressure/flow/power differ over time.
|
||||||
|
More mismatch → higher drift score → worse health.
|
||||||
|
|
||||||
|
Efficiency penalty = how far the current efficiency is from the best efficiency point.
|
||||||
|
Further from the peak efficiency → higher penalty → worse health.
|
||||||
|
|
||||||
|
3. These are combined into one score:
|
||||||
|
score01 = 0.4 * unavailability
|
||||||
|
+ 0.4 * driftScore
|
||||||
|
+ 0.2 * effPenalty;
|
||||||
|
|
||||||
|
So: availability (40%) + drift (40%) + efficiency loss (20%).
|
||||||
|
|
||||||
|
4. Convert to index 0–5:
|
||||||
|
index = round(score01 * 5)
|
||||||
|
Clamp between 0 and 5 and store in this.assetHealth.index.
|
||||||
|
|
||||||
|
Summary: Health index = mix of downtime, sensor/prediction mismatch, and efficiency loss, scaled to a 0–5 scale (0 good, 5 bad).
|
||||||
|
|
||||||
|
Remaining Useful Life: the estimated amount of time an asset has until it becomes unusable or requires replacement.
|
||||||
|
How RUL is being calculated: combination of MTBF and Asset Health Index
|
||||||
|
|
||||||
---KPI message---
|
---KPI message---
|
||||||
The message consists of the following components:
|
The message consists of the following components:
|
||||||
- asset tagnumber:
|
- asset tagnumber: unique identifier of an asset
|
||||||
|
- Maintenance mode: If asset in maintenance, this returns true, else this return false
|
||||||
|
- Maintenance Time: Total time the asset has been in maintenance
|
||||||
- asset availability
|
- asset availability
|
||||||
- mean time between failures
|
- mean time between failures
|
||||||
- mean time to repair
|
- mean time to repair
|
||||||
- asset health index
|
- asset health index
|
||||||
- asset health color: Gives a color based on the asset health index (0 = Darkgreen, 1 = Green, 2 = Yellow, 3 = Orange, 4 = Red, 5 = Darkred.)
|
- asset health color: Gives a color based on the asset health index (0 = Darkgreen, 1 = Green, 2 = Yellow, 3 = Orange, 4 = Red, 5 = Darkred.)
|
||||||
- total failures: the total number of failures that have occured for a particular asset
|
- total failures: the total number of failures that have occured for a particular asset
|
||||||
|
- Remaining Useful Life: the length from the current time to the end of the useful life
|
||||||
|
|
||||||
|
Example message:
|
||||||
|
{
|
||||||
|
asset_tag_number: "L001"
|
||||||
|
maintenance_mode: false
|
||||||
|
maintenance_time: 0.23494861111111115
|
||||||
|
kpi_asset_availability: 95.83
|
||||||
|
kpi_mtbf: 1.3505209027777778
|
||||||
|
kpi_mttr: 0.05873715277777779
|
||||||
|
kpi_asset_health_index: 2
|
||||||
|
kpi_asset_health_color: "#FFFF00"
|
||||||
|
kpi_total_failures: 4
|
||||||
|
remaining_useful_life: 1.0804167222222223
|
||||||
|
}
|
||||||
@@ -96,7 +96,11 @@ class Machine {
|
|||||||
lastRepairTime: null,
|
lastRepairTime: null,
|
||||||
MTBF: 0,
|
MTBF: 0,
|
||||||
MTTR: 0,
|
MTTR: 0,
|
||||||
availability: 0
|
availability: 1,
|
||||||
|
maintenanceMode: false,
|
||||||
|
lastFailureRuntime: 0,
|
||||||
|
lastRUL: null, // remember previous RUL value
|
||||||
|
lastFailureCause: null
|
||||||
};
|
};
|
||||||
|
|
||||||
this.assetHealth = {
|
this.assetHealth = {
|
||||||
@@ -116,47 +120,6 @@ class Machine {
|
|||||||
|
|
||||||
this._handleStateChangeForKPI(stateStr);
|
this._handleStateChangeForKPI(stateStr);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// --- KPI tracking ---
|
|
||||||
this.kpi = {
|
|
||||||
failures: 0,
|
|
||||||
totalRuntimeHours: 0,
|
|
||||||
totalDowntimeHours: 0,
|
|
||||||
lastFailureTime: null,
|
|
||||||
lastRepairTime: null,
|
|
||||||
MTBF: 0,
|
|
||||||
MTTR: 0,
|
|
||||||
availability: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
this.assetHealth = {
|
|
||||||
index: 0 // 0 = optimal, 5 = failure
|
|
||||||
};
|
|
||||||
|
|
||||||
this.state.emitter.on('stateChange', (payload) => {
|
|
||||||
|
|
||||||
const stateStr = typeof payload === 'string'
|
|
||||||
? payload
|
|
||||||
: (payload?.state ?? payload?.newState ?? payload);
|
|
||||||
|
|
||||||
if (typeof stateStr !== 'string') {
|
|
||||||
this.logger.warn(`stateChange event without parsable state: ${JSON.stringify(payload)}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._handleStateChangeForKPI(stateStr);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
_updateState(){
|
|
||||||
const isOperational = this._isOperationalState();
|
|
||||||
if(!isOperational){
|
|
||||||
//overrule the last prediction this should be 0 now
|
|
||||||
this.measurements.type("flow").variant("predicted").position("downstream").value(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateState(){
|
_updateState(){
|
||||||
@@ -299,10 +262,8 @@ _callMeasurementHandler(measurementType, value, position, context) {
|
|||||||
return await this.setpoint(parameter);
|
return await this.setpoint(parameter);
|
||||||
|
|
||||||
case "entermaintenance":
|
case "entermaintenance":
|
||||||
|
|
||||||
return await this.executeSequence(parameter);
|
return await this.executeSequence(parameter);
|
||||||
|
|
||||||
|
|
||||||
case "exitmaintenance":
|
case "exitmaintenance":
|
||||||
return await this.executeSequence(parameter);
|
return await this.executeSequence(parameter);
|
||||||
|
|
||||||
@@ -649,12 +610,7 @@ _callMeasurementHandler(measurementType, value, position, context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////
|
///////////////////////////// Calculate Asset Health Index /////////////////////////////
|
||||||
/**
|
|
||||||
* Compute a single drift score in [0..1] using predicted vs measured series.
|
|
||||||
* Uses min/max of the *predicted* window as normalization range.
|
|
||||||
* If no usable data -> returns 0 (neutral).
|
|
||||||
*/
|
|
||||||
_computeDriftScore() {
|
_computeDriftScore() {
|
||||||
try {
|
try {
|
||||||
const metrics = [
|
const metrics = [
|
||||||
@@ -693,30 +649,21 @@ _callMeasurementHandler(measurementType, value, position, context) {
|
|||||||
|
|
||||||
_calculateAssetHealthIndex() {
|
_calculateAssetHealthIndex() {
|
||||||
try {
|
try {
|
||||||
// 1) Hard fail -> worst health
|
if (["maintenance"].includes(this.state?.getCurrentState?.())){
|
||||||
// if (this.state?.getCurrentState && this.state.getCurrentState() === "failed")
|
|
||||||
if (["off"].includes(this.state?.getCurrentState?.())){
|
|
||||||
this.assetHealth.index = 5;
|
this.assetHealth.index = 5;
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) Inputs (clamped to 0..1)
|
|
||||||
const availability = typeof this.kpi?.availability === 'number' ? this.kpi.availability : 1;
|
const availability = typeof this.kpi?.availability === 'number' ? this.kpi.availability : 1;
|
||||||
const unavailability = 1 - Math.max(0, Math.min(1, availability));
|
const unavailability = 1 - Math.max(0, Math.min(1, availability));
|
||||||
|
|
||||||
const effPenalty = Math.max(0, Math.min(1, typeof this.relDistFromPeak === 'number' ? this.relDistFromPeak : 0));
|
const effPenalty = Math.max(0, Math.min(1, typeof this.relDistFromPeak === 'number' ? this.relDistFromPeak : 0));
|
||||||
|
|
||||||
const driftScore = this._computeDriftScore(); // 0..1
|
const driftScore = this._computeDriftScore();
|
||||||
|
const wAvail = 0.2; // unavailability weight
|
||||||
// 3) Blend (weights sum to 1.0)
|
|
||||||
// Tweak these if you like: e.g. make drift more/less important.
|
|
||||||
const wAvail = 0.4; // unavailability weight
|
|
||||||
const wDrift = 0.4; // drift weight
|
const wDrift = 0.4; // drift weight
|
||||||
const wEff = 0.2; // efficiency distance weight
|
const wEff = 0.4; // efficiency distance weight
|
||||||
|
|
||||||
const score01 = (wAvail * unavailability) + (wDrift * driftScore) + (wEff * effPenalty);
|
const score01 = (wAvail * unavailability) + (wDrift * driftScore) + (wEff * effPenalty);
|
||||||
|
|
||||||
// 4) Scale to 0..5 integer, clamp
|
|
||||||
const index = Math.max(0, Math.min(5, Math.round(score01 * 5)));
|
const index = Math.max(0, Math.min(5, Math.round(score01 * 5)));
|
||||||
|
|
||||||
this.assetHealth.index = index;
|
this.assetHealth.index = index;
|
||||||
@@ -728,56 +675,68 @@ _callMeasurementHandler(measurementType, value, position, context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_handleStateChangeForKPI(newState) {
|
_registerFailure(cause, runtimeOverride) {
|
||||||
const now = Date.now();
|
const runtime = runtimeOverride ?? this.state.getRunTimeHours();
|
||||||
const runtime = this.state.getRunTimeHours();
|
const maintenance_time = this.state.getMaintenanceTimeHours();
|
||||||
const lastState = this.state.getPreviousState?.() || "unknown";
|
|
||||||
|
|
||||||
// --- Treat OFF as failure and start of downtime ---
|
this.kpi.failures += 1;
|
||||||
if (newState === "off") {
|
this.kpi.rulFailureTriggered = false;
|
||||||
this.kpi.failures++; // always count a new failure when OFF
|
this.kpi.lastFailureTime = Date.now();
|
||||||
this.kpi.lastFailureTime = now; // mark the start of downtime
|
this.kpi.lastFailureRuntime = runtime;
|
||||||
this.logger.warn(`Machine OFF (counted as failure). Total failures: ${this.kpi.failures}`);
|
this.kpi.lastFailureCause = cause;
|
||||||
}
|
|
||||||
|
|
||||||
// --- When we leave OFF and become OPERATIONAL, book downtime ---
|
|
||||||
if (newState === "operational") {
|
|
||||||
// Only calculate downtime if we had an OFF period before
|
|
||||||
if (this.kpi.lastFailureTime != null) {
|
|
||||||
const downtimeHours = (now - this.kpi.lastFailureTime) / 3600000;
|
|
||||||
this.kpi.totalDowntimeHours += downtimeHours;
|
|
||||||
this.kpi.lastRepairTime = now; // moment of "repaired"
|
|
||||||
this.kpi.lastFailureTime = null; // close downtime window
|
|
||||||
this.logger.info(`OFF → OPERATIONAL. Added ${downtimeHours.toFixed(2)}h downtime.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Compute KPI Metrics ---
|
|
||||||
const failures = this.kpi.failures;
|
const failures = this.kpi.failures;
|
||||||
const downtime = this.kpi.totalDowntimeHours;
|
|
||||||
|
|
||||||
// If no failures yet: MTBF = total runtime; MTTR = 0
|
// If no failures yet: MTBF = total runtime & MTTR = 0
|
||||||
this.kpi.MTBF = failures > 0 ? runtime / failures : runtime;
|
this.kpi.MTBF = failures > 0 ? runtime / failures : runtime;
|
||||||
this.kpi.MTTR = failures > 0 ? downtime / failures : 0;
|
this.kpi.MTTR = failures > 0 ? maintenance_time / failures : 0;
|
||||||
|
|
||||||
// --- Compute Availability ---
|
|
||||||
const mtbf = this.kpi.MTBF ?? 0;
|
const mtbf = this.kpi.MTBF ?? 0;
|
||||||
const mttr = this.kpi.MTTR ?? 0;
|
const mttr = this.kpi.MTTR ?? 0;
|
||||||
|
|
||||||
if (mtbf <= 0 && mttr <= 0) {
|
if (mtbf <= 0 && mttr <= 0) {
|
||||||
this.kpi.availability = 1; // Default: 100% if no data
|
this.kpi.availability = 1;
|
||||||
} else {
|
} else {
|
||||||
const availability = mtbf / (mtbf + mttr);
|
const availability = mtbf / (mtbf + mttr);
|
||||||
this.kpi.availability = Math.min(1, Math.max(0, availability)); // clamp 0–1
|
this.kpi.availability = Math.min(1, Math.max(0, availability));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.debug(
|
this.logger.warn(
|
||||||
`KPI updated — MTBF: ${this.kpi.MTBF.toFixed(2)}h, MTTR: ${this.kpi.MTTR.toFixed(2)}h, ` +
|
`Failure registered (cause=${cause}). Total failures=${this.kpi.failures}, runtime=${runtime.toFixed(2)}h`
|
||||||
`Availability: ${(this.kpi.availability * 100).toFixed(2)}%`
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////
|
_handleStateChangeForKPI(newState) {
|
||||||
|
const runtime = this.state.getRunTimeHours();
|
||||||
|
|
||||||
|
if (newState === "maintenance") {
|
||||||
|
if (this.kpi.rulFailureTriggered) {
|
||||||
|
this.kpi.rulFailureTriggered = false;
|
||||||
|
this._registerFailure("MAINTENANCE", runtime);
|
||||||
|
} else {
|
||||||
|
this._registerFailure("MAINTENANCE", runtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.kpi.maintenanceMode = true;
|
||||||
|
} else {
|
||||||
|
this.kpi.maintenanceMode = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recalculate KPIs after possibly registering a failure:
|
||||||
|
const failures = this.kpi.failures;
|
||||||
|
const maintenance_time = this.state.getMaintenanceTimeHours();
|
||||||
|
this.kpi.MTBF = failures > 0 ? runtime / failures : runtime;
|
||||||
|
this.kpi.MTTR = failures > 0 ? maintenance_time / failures : 0;
|
||||||
|
const mtbf = this.kpi.MTBF ?? 0;
|
||||||
|
const mttr = this.kpi.MTTR ?? 0;
|
||||||
|
|
||||||
|
if (mtbf <= 0 && mttr <= 0) {
|
||||||
|
this.kpi.availability = 1;
|
||||||
|
} else {
|
||||||
|
const availability = mtbf / (mtbf + mttr);
|
||||||
|
this.kpi.availability = Math.min(1, Math.max(0, availability));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
calcDistanceFromPeak(currentEfficiency,peakEfficiency){
|
calcDistanceFromPeak(currentEfficiency,peakEfficiency){
|
||||||
return Math.abs(currentEfficiency - peakEfficiency);
|
return Math.abs(currentEfficiency - peakEfficiency);
|
||||||
@@ -871,6 +830,7 @@ _handleStateChangeForKPI(newState) {
|
|||||||
if (power != 0 && flow != 0) {
|
if (power != 0 && flow != 0) {
|
||||||
// Calculate efficiency after measurements update
|
// Calculate efficiency after measurements update
|
||||||
this.measurements.type("efficiency").variant(variant).position('atEquipment').value((flow / power));
|
this.measurements.type("efficiency").variant(variant).position('atEquipment').value((flow / power));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.measurements.type("efficiency").variant(variant).position('atEquipment').value(null);
|
this.measurements.type("efficiency").variant(variant).position('atEquipment').value(null);
|
||||||
}
|
}
|
||||||
@@ -879,6 +839,65 @@ _handleStateChangeForKPI(newState) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
calculateSimpleRUL() {
|
||||||
|
const mtbf = this.kpi?.MTBF ?? 0;
|
||||||
|
const healthIndex = typeof this.assetHealth?.index === "number"
|
||||||
|
? this.assetHealth.index
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
if (this.kpi?.rulFailureTriggered) {
|
||||||
|
this.kpi.lastRUL = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mtbf <= 0) {
|
||||||
|
this.logger.debug("No MTBF available, RUL cannot be estimated.");
|
||||||
|
this.kpi.lastRUL = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const clampedHI = Math.min(5, Math.max(0, healthIndex));
|
||||||
|
const runtime = this.state?.getRunTimeHours?.() ?? 0;
|
||||||
|
const lastFailureRuntime = this.kpi?.lastFailureRuntime ?? 0;
|
||||||
|
const ageSinceLastFailure = Math.max(0, runtime - lastFailureRuntime);
|
||||||
|
|
||||||
|
const fractionByHealth = (5 - clampedHI) / 5;
|
||||||
|
const fractionByAge = Math.max(0, 1 - ageSinceLastFailure / mtbf);
|
||||||
|
const fractionLeft = Math.min(fractionByHealth, fractionByAge);
|
||||||
|
|
||||||
|
let rul = mtbf * fractionLeft;
|
||||||
|
if (rul < 0) rul = 0;
|
||||||
|
|
||||||
|
const prevRUL = this.kpi.lastRUL ?? null;
|
||||||
|
const EPS = 1e-3;
|
||||||
|
|
||||||
|
const state = this.state?.getCurrentState?.();
|
||||||
|
const isOperational = ["operational", "accelerating", "decelerating"].includes(state);
|
||||||
|
|
||||||
|
if (isOperational) {
|
||||||
|
const hadPrev = prevRUL !== null;
|
||||||
|
const wasPositive = hadPrev && prevRUL > EPS;
|
||||||
|
const isNowZeroish = rul <= EPS;
|
||||||
|
const isDecreasing = hadPrev && rul <= prevRUL + EPS;
|
||||||
|
|
||||||
|
if (wasPositive && isNowZeroish && isDecreasing) {
|
||||||
|
this.kpi.rulFailureTriggered = true;
|
||||||
|
|
||||||
|
this.kpi.lastFailureTime = Date.now();
|
||||||
|
this.kpi.lastFailureRuntime = runtime;
|
||||||
|
this.kpi.lastFailureCause = "RUL";
|
||||||
|
|
||||||
|
rul = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.kpi.lastRUL = rul;
|
||||||
|
|
||||||
|
return rul;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
updateCurve(newCurve) {
|
updateCurve(newCurve) {
|
||||||
this.logger.info(`Updating machine curve`);
|
this.logger.info(`Updating machine curve`);
|
||||||
const newConfig = { asset: { machineCurve: newCurve } };
|
const newConfig = { asset: { machineCurve: newCurve } };
|
||||||
@@ -940,14 +959,20 @@ _handleStateChangeForKPI(newState) {
|
|||||||
output["cog"] = this.cog; // flow / power efficiency
|
output["cog"] = this.cog; // flow / power efficiency
|
||||||
output["NCog"] = this.NCog; // normalized cog
|
output["NCog"] = this.NCog; // normalized cog
|
||||||
output["NCogPercent"] = Math.round(this.NCog * 100 * 100) / 100 ;
|
output["NCogPercent"] = Math.round(this.NCog * 100 * 100) / 100 ;
|
||||||
|
|
||||||
|
// KPIs
|
||||||
output["kpi_MTBF"] = this.kpi.MTBF;
|
output["kpi_MTBF"] = this.kpi.MTBF;
|
||||||
output["kpi_MTTR"] = this.kpi.MTTR;
|
output["kpi_MTTR"] = this.kpi.MTTR;
|
||||||
output["kpi_assetAvailability"] = Math.round(this.kpi.availability * 100 * 100) / 100;
|
output["kpi_assetAvailability"] = Math.round(this.kpi.availability * 100 * 100) / 100;
|
||||||
output["kpi_totalFailuresCount"] = this.kpi.failures;
|
output["kpi_totalFailuresCount"] = this.kpi.failures;
|
||||||
output["asset_tag_number"] = 'L001';
|
output["asset_tag_number"] = 'L001'; // hardcoded for now
|
||||||
|
output["maintenanceMode"] = this.kpi.maintenanceMode;
|
||||||
// output["asset_tag_number"] = this.assetTagNumber;
|
|
||||||
output["maintenanceTime"] = this.state.getMaintenanceTimeHours();
|
output["maintenanceTime"] = this.state.getMaintenanceTimeHours();
|
||||||
|
output["rul_hours"] = this.calculateSimpleRUL();
|
||||||
|
this._calculateAssetHealthIndex();
|
||||||
|
output["assetHealthIndex"] = this.assetHealth.index;
|
||||||
|
const healthColors = ["#006400", "#008000", "#FFFF00", "#FFA500", "#FF0000", "#8B0000"]; // 0 = darkgreen, 1 = green, 2 = yellow, 3 = orange, 4 = red, 5 = darkred
|
||||||
|
output["assetHealthColor"] = healthColors[this.assetHealth.index] || "unknown";
|
||||||
|
|
||||||
if(this.flowDrift != null){
|
if(this.flowDrift != null){
|
||||||
const flowDrift = this.flowDrift;
|
const flowDrift = this.flowDrift;
|
||||||
@@ -962,21 +987,6 @@ _handleStateChangeForKPI(newState) {
|
|||||||
output["effRelDistFromPeak"] = this.relDistFromPeak;
|
output["effRelDistFromPeak"] = this.relDistFromPeak;
|
||||||
//this.logger.debug(`Output: ${JSON.stringify(output)}`);
|
//this.logger.debug(`Output: ${JSON.stringify(output)}`);
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////
|
|
||||||
// this._calculateAssetHealthIndex();
|
|
||||||
// output["assetHealthIndex"] = this.assetHealth.index;
|
|
||||||
|
|
||||||
this._calculateAssetHealthIndex();
|
|
||||||
output["assetHealthIndex"] = this.assetHealth.index;
|
|
||||||
|
|
||||||
// 0 = darkgreen, 1 = green, 2 = yellow, 3 = orange, 4 = red, 5 = darkred
|
|
||||||
// const healthColors = ["darkgreen", "green", "yellow", "orange", "red", "darkred"];
|
|
||||||
const healthColors = ["#006400", "#008000", "#FFFF00", "#FFA500", "#FF0000", "#8B0000"];
|
|
||||||
output["assetHealthColor"] = healthColors[this.assetHealth.index] || "unknown";
|
|
||||||
//////////////////////////
|
|
||||||
|
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user