To those more experienced in node red development, this may be obvious, but I'll ask anyway.
Within my node red flow, I have a function node containing a javascript class that only exposes static members. Here's an example:
class MeasurementsList {
static INTERNAL_LIST_CONTEXT_NAME = "INTERNAL_LIST_CONTEXT_NAME";
static get availableMeasurements() { //this is an array
const tempMeasurementsInternalList = context.get(INTERNAL_LIST_CONTEXT_NAME);
const measurementsInternalList = tempMeasurementsInternalList?.length ? tempMeasurementsInternalList : new Array();
return measurementsInternalList;
}
...
}
In short, I want to be able to manipulate the array like so:
MeasurementsList.availableMeasurements.push(newMeasurementObject);
. However, I'm struggling to make the availableMeasurements
array persistent across different msg.payload
s.
This is what I intend to achieve:
MeasurementsList.availableMeasurements.push(msg.payload1.newMeasurementObject);
...
MeasurementsList.availableMeasurements.push(msg.payload999.newMeasurementObject);
MeasurementsList.availableMeasurements.push(msg.payload1000.newMeasurementObject);
...
Is it possible to accomplish this in node-red with javascript? How should I handle the context variable?
Edit 1:
I've refactored my former static member class to an instantiable one, located on the [On Start
] tab:
https://i.sstatic.net/S90Ti.png
// Code added here will be run once
// whenever the node is started.
class Measurement {
constructor(time, device, temperatureC, maxAgeMs) {
this.time = time;
this.device = device;
this.temperatureC = temperatureC;
this.maxAgeMs = maxAgeMs;
}
}
class MeasurementsList {
constructor() {
this.#measurementsList = new Array();
}
/**
* @param {Measurement} measurement
*/
refreshAndAdd(measurement) {
this.#removeOutdatedValuesAndSortByTemperaturesAscending();
this.#measurementsList.push(measurement);
return {
"maxMeasurement": this.#maxMeasurement(),
"meanTemperatureC": this.#meanTemperatureC(),
"minMeasurement": this.#minMeasurement()
};
}
get length() {
return this.#measurementsList.length;
}
#maxMeasurement() {
const maxIndex = this.#measurementsList.length - 1;
return this.#measurementsList[maxIndex];
}
#meanTemperatureC() {
let sum = 0;
this.#measurementsList
.forEach((m) => {
sum += m.temperatureC;
});
const mean = sum / this.#measurementsList.length;
return mean;
}
#minMeasurement() {
const minIndex = 0;
return this.#measurementsList[minIndex];
}
#removeOutdatedValuesAndSortByTemperaturesAscending() {
const currentTime = Date.now();
this.#measurementsList = this.#measurementsList
.filter((m) => {
return (currentTime - m.time) < m.maxAgeMs;
})
.sort((m1, m2) => {
return m1.temperatureC - m2.temperatureC
});
}
}
let measurementsList = new MeasurementsList();
However, there are certain aspects of scope that confuse me. I declared and instantiated my MeasurementsList
class on the [On Start
] tab as measurementsList
. But I can't access measurementsList
on the [On Message
] tab, nor can I access the Message
class. Did I misunderstand your answer, Mr. @hardillb?
https://i.sstatic.net/2EdOn.png
Question: What steps should I take to access my measurementsList
on the [On Message
] tab?