Calculate the mean of data pairs in an Object

I'm creating a flow to monitor signal levels on a selected radio frequency. The main component is the rtl-power node and this produces output in the format shown at the end of this post.

In order to cope with slightly off frequency transmissions, it is necessary to measure the signal level over a narrow range of frequencies. The data I need is in the 'results' object which is supplied as pairs, the first of which is the frequency and the second is the signal level. For each message, I want to take the mean of all the signal levels and send the result to a Dashboard chart for plotting. I can easily extract individual items from the results object but I want to extract all the signal levels, calculate the mean and make that the output message. Just to make things a little more complex, I want to be able to easily change frequency so I won't know the individual frequency steps.

Is there an easy way to iterate over the frequency values using a wildcard?

Thanks,

Mike

8/1/2019, 8:51:33 AMnode: 6e2715a2.3838bc135050000 : msg.payload : Object
object
low: 135049000
high: 135051000
bucket: 62
samples: 348600
results: object
135049000: -34.21
135049062: -33.84
135049124: -34.02
135049186: -34.88
135049248: -34.08
135049310: -34.5
135049372: -34.08
135049434: -34.09
135049496: -34.38
135049558: -34.48
135049620: -33.73
135049682: -33.97
135049744: -33.74
135049806: -34.01
135049868: -33.65
135049930: -33.63
135049992: -33.7
135050054: -33.7
135050116: -33.7
135050178: -34.54
135050240: -34.17
135050302: -34.12
135050364: -33.61
135050426: -33.99
135050488: -33.82
135050550: -34.35
135050612: -34.28
135050674: -34.47
135050736: -33.98
135050798: -34.02
135050860: -34.12
135050922: -33.99
135050984: -33.99

You can iterate through the properties of an object using the method described in the to answer here: https://stackoverflow.com/questions/8312459/iterate-through-object-properties

Something like this? Dunno, haven't tested

function getAverage(results) {
  let signalTotal = 0;
  let numberOfFreqs = 0;
  let avarageSignal = 0;
  for (let frequency in results) {
    signalTotal += results[frequency];
    numberOfFreqs += 1;
  }
  return signalTotal / numberOfFreqs;
}

getAverage(msg.payload.results);

Not sure what you mean here though:

Just to make things a little more complex, I want to be able to easily change frequency so I won't know the individual frequency steps.

Note that you should use hasOwnProperty() as in the link I posted so you only get the relevant properties and not the base Object properties.

Thanks Colin and realjax.

The final function node code I used produce the average is shown below. Happy to consider alternatives if there's a better way to do this.

function getAverage(results) {
let signalTotal = 0;
let numberOfFreqs = 0;
let avarageSignal = 0;
for (let frequency in results) {
signalTotal += results[frequency];
numberOfFreqs += 1;
}
return signalTotal / numberOfFreqs;
}
signal = getAverage(msg.payload.results);
signal = signal.toFixed(2);
msg={payload:signal};
return msg;

Just a note: it is a good practice not to create a completely new message in a flow, but to modify just the properties you need. Otherwise this could break enclosing nodes, which could rely on certain properties to be present, e.g. in a request-response scheme.

So msg.payload = signal; should suffice.