Function: sendIt - avoid incorrect values

Hi, i´m using the following function to send some values to my influxdb:

function sendIt(topic, address, roundTo) {
    let m = {
        topic: topic,
        payload: parseFloat(msg.payload[address].toFixed(roundTo))
    } 
    node.send(m);
}
sendIt("VLT", 40008, 1);
sendIt("RLT", 40012, 1);
sendIt("WWo", 40013, 1);
sendIt("WW",  40014, 1);
sendIt("KTe", 40015, 1);
sendIt("KTa", 40016, 1);
sendIt("Hz",  43136, 0);
sendIt("GM",  43005, 0);
sendIt("WT%", 43437, 0);
sendIt("KT%", 43439, 0);
sendIt("HG",  40018, 1);
sendIt("Vol", 40072, 1);
sendIt("Pth", 'Pth', 0);

sometimes I get incorrect values from: VLT, RLT, WWo.
for example: -78°C

I want to prevent that these speaks get into my database.
Is there a way to integrate this into the function?

if "WWo" is < 0°C => "WWo" = 0°C

greetings

Without seeing the input msg.payload object we probably can't help here.

And what have you tried?

this is a bit confusing but i guess you mean if the value for address 40013 is < 0, set it to 0. If yes, then something like:

function sendIt(topic, address, roundTo) {
    let value = msg.payload[address]
    if (topic === 'WWo' && value < 0) {
        value = 0
    }
    const m = {
        topic: topic,
        payload: parseFloat(value.toFixed(roundTo))
    }
    node.send(m);
}

TBH, this is probably a bit better:

function sendIt(topic, address, roundTo, min, max) {
    let value = msg.payload[address]
    if (typeof min === "number") {
        if (value < min) {
            value = min
        }
    }
    if (typeof max === "number") {
        if (value > max) {
            value = max
        }
    }
    const m = {
        topic: topic,
        payload: parseFloat(value.toFixed(roundTo))
    }
    node.send(m);
}

sendIt("VLT", 40008, 1, 0, null); // min 0
sendIt("RLT", 40012, 1, 0.1, null); // min 0.1
sendIt("WWo", 40013, 1, -0.5, 1.9); // min -0.5, max 1.9
sendIt("WW", 40014, 1, null, 10.5); // max 10.5
sendIt("KTe", 40015, 1); // no limits
sendIt("KTa", 40016, 1); // no limits
sendIt("Hz", 43136, 0); // etc
sendIt("GM", 43005, 0);
sendIt("WT%", 43437, 0);
sendIt("KT%", 43439, 0);
sendIt("HG", 40018, 1);
sendIt("Vol", 40072, 1);
sendIt("Pth", 'Pth', 0);
2 Likes

BTW, you should NEVER round values going into the database.

Otherwise if you ever do a summation across the month or year, you will lose precision.

Round them upon display only.

I do things slightly differently because I'm more interested in ensuring that I don't end up with text values instead of numbers:

All of my sensor outputs to to the one_week db and the function node ensures that data is correctly formed.

/**
 * Validate input suitable for the influxdb-out node.
 * We will ALWAYS use the "array containing two objects" payload
 * OR the singe Object payload (if no tags being used).
 * See the Description tab for more details.
 */

// check measurement field is set - if not exit with error
if ( ! msg.measurement ) {
    node.error('msg.measurement is missing')
    node.send([null,msg])
    return
}

let fields,tags

// if payload is an object, assume that it contains fieldName:fieldValue pairs
if ( msg.payload!== null && msg.payload.constructor.name === 'Object' ) {
    fields = msg.payload
} else if ( msg.payload!== null && msg.payload.constructor.name === 'Array' ) {
    node.error('msg.payload cannot be an array. It must be an object containing fieldName:fieldValue pairs or a single value (which would be written to the `value` field name).')
    node.send([null,msg])
    return
} else {
    // Otherwise, we always use 'value' as the default field name
    fields = {'value': msg.payload}
}

const lstFields = Object.keys(fields)

// check to make sure that there is a value field name - if not, continue but with a warning
if ( ! lstFields.includes('value') ) {
    // Lets us turn off the warning if we know what we are doing :-)
    if ( msg.noValueField !== true )
        node.warn('Default field name "value" not present, was that deliberate? Set msg.noValueField=true or use the `value` field name to avoid this msg')
}

// check to make sure that all field values are numeric - if not, exit with a warning
let allNumeric = true
lstFields.forEach( key => {
    // I use On/Off for simple switch values in MQTT but these are not useful
    // in InfluxDB, so translate them to ON=1 and OFF=0 (ignoring case).
    try {
        if ( fields[key].toLowerCase() === 'on' ) fields[key] = 1
        if ( fields[key].toLowerCase() === 'off' ) fields[key] = 0
    } catch (e) {}

    // then check to make sure the field is actually a number
    if ( parseFloat(fields[key]) !== fields[key] ) {
        node.error(`Field msg.payload.${key} is not numeric. Only use numbers for field values, text should go in tags. Value=${fields[key]}`)
        allNumeric = false
        node.send([null,msg])
        return
    }
})
// @ts-ignore
if ( allNumeric === false ) {
    return
}

// check to make sure that if msg.tags is present, it is an object - if not, exit with a warning
if ( msg.tags ) {
    if ( !(msg.tags!== null && msg.tags.constructor.name === 'Object') ) {
        node.error('msg.tags is not an object - it must contain tagName:tagValue pairs')
        node.send([null,msg])
        return
    }
    tags = msg.tags
}

// Format the output to go to the InfluxDB out node
if ( msg.tags ) {
    msg.payload = [
        fields,
        tags,
    ]
} else {
    msg.payload = fields
}


return msg

This has saved me loads of grief over the years. :grinning:

thank you

@Steve-Mcl I´m rouding because of the node before: calculate ⌀ of 1min, so that I have the same decimal place again in my database every minute, that's accurate enough.

@TotallyInformation I have to take a look at this in peace :wink:

What benefit do you see to throwing away information?