Help with function node and multiple inputs

Hey all, Im terrible with programing, I have made it this far by reading and combining multiple tutorials, however im not sure what I am missing and I feel like I am bashing my head against the wall trying to figure this out..

I have a raspberry pi zero w, i have a BME680, and I am using the BME680 with the Pimoroni library, which does not have altitude.

I am trying to use the input of a dashboard text node for the standard pressure input, and the sensor data via msg.payload.Pressure_HPA in a function node to calculate altitude with the formula:

pressure altitude = ((standard pressure – current pressure) * 1000 ) + field elevation

Capture

The prepare pressure function contains:
prepresss
And will return
preppres

Is the function node the correct way to go about calculating altitude? Am I doing this all wrong? Could someone please at least point me in the right direction?

See this article in the cookbook for an example of how to join messages into one object.

1 Like

If you do not like programming, I cannot understand why you are using function nodes for this.

If you need to specify altitude as input use a change node to store the value into a flow variable and use the content in another change node to modify the value output of your sensor with your formula.

1 Like

I was very tired and should have thought about it over sleep, but i thought id ask anyways. I am using flow variables elsewhere in my flow, but i didnt make the connection. Thanks for the help :slight_smile:

1 Like

Here is my current setup, i know this is wrong, but im not sure what I am doing wrong. I have spent all day looking through tutorials but no matter what I do the output is always "The input value (undefined) is not a number". you can see in this picture, that message comes from a different node, but this time it is because there is something wrong with how the function is currently written.

sorry for being such a noob, im trying to learn

flow

Heres the altimeter setting, I forgot to include this screenshot.
alti

Place a debug node to catch the incoming msg. to the function node, set the debug node to complete msg. object.

What do you see?

object

For mat your post please correctly, you need to Copy the value of the debug and post it in between ```

image

And also post you flow, it is easier to see what is going on.

Change the function to


   let result = (altimeter - pressure) * 1000
   .... whatever is under the error message

   return result

You cannot have a calculation as an argument in a function definition so if there is further calculations under the error message you would need

function altitude(altimeter, pressure) {
  result = (altimeter - pressure) * 10000
  rest of calculation

   return result
}

msg.payload = altitude(altimeter, pressure)

return msg

[{"id":"f8535fdf67d273c2","type":"tab","label":"Flow 1","disabled":true,"info":"","env":[]},{"id":"6557bcc7108c8f9c","type":"function","z":"f8535fdf67d273c2","name":"Prep Pres","func":"var newMsg={};\nnewMsg.topic = 'Pressure_HPA';\nnewMsg.payload = msg.payload.Pressure_HPA\nreturn newMsg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":960,"y":160,"wires":[["44bba037c3a47aa4"]]},{"id":"66221b9114fd8b9c","type":"function","z":"f8535fdf67d273c2","name":"Prepare data","func":"var newMsg={temp:{},pressure:{},humidity:{},voc:{}};\nvar temp_min=flow.get('temp_min') || 100;\nvar temp_max=flow.get('temp_max') || -100;\nvar pressure_min=flow.get('pressure_min') || 5000;\nvar pressure_max=flow.get('pressure_max') || -5000;\nvar humidity_min=flow.get('humidity_min') || 100;\nvar humidity_max=flow.get('humidity_max') || -100;\nvar voc_min=flow.get('voc_min') || 500000;\nvar voc_max=flow.get('voc_max') || -500000;\n//\nnewMsg.payload = msg.payload;\n\n//\n\nif (msg.payload.Temperature_oC < temp_min) {\n   newMsg.temp.min = msg.payload.Temperature_oC;\n   flow.set('temp_min', msg.payload.Temperature_oC);\n} else {\n   newMsg.temp.min = temp_min;\n}\nif (msg.payload.Temperature_oC > temp_max) {\n   newMsg.temp.max = msg.payload.Temperature_oC;\n   flow.set('temp_max', msg.payload.Temperature_oC);\n} else {\n   newMsg.temp.max = temp_max;\n}\n\n//\n\nif (msg.payload.Pressure_HPA < pressure_min) {\n   newMsg.pressure.min = msg.payload.Pressure_HPA;\n   flow.set('pressure_min', msg.payload.Pressure_HPA);\n} else {\n   newMsg.pressure.min = pressure_min;\n}\nif (msg.payload.Pressure_HPA > pressure_max) {\n   newMsg.pressure.max = msg.payload.Pressure_HPA;\n   flow.set('pressure_max', msg.payload.Pressure_HPA);\n} else {\n   newMsg.pressure.max = pressure_max;\n}\n\n//\n\nif (msg.payload.RelativeHumidity_percent < humidity_min) {\n   newMsg.humidity.min = msg.payload.RelativeHumidity_percent;\n   flow.set('humidity_min', msg.payload.RelativeHumidity_percent);\n} else {\n   newMsg.humidity.min = humidity_min;\n}\nif (msg.payload.RelativeHumidity_percent > humidity_max) {\n   newMsg.humidity.max = msg.payload.RelativeHumidity_percent;\n   flow.set('humidity_max', msg.payload.RelativeHumidity_percent);\n} else {\n   newMsg.humidity.max = humidity_max;\n}\n\n//\n\nif (msg.payload.Resistance_Ohms < voc_min) {\n   newMsg.voc.min = msg.payload.Resistance_Ohms;\n   flow.set('voc_min', msg.payload.Resistance_Ohms);\n} else {\n   newMsg.voc.min = voc_min;\n}\nif (msg.payload.Resistance_Ohms > voc_max) {\n   newMsg.voc.max = msg.payload.Resistance_Ohms;\n   flow.set('voc_max', msg.payload.Resistance_Ohms);\n} else {\n   newMsg.voc.max = voc_max;\n}\n\nreturn newMsg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":550,"y":180,"wires":[["6557bcc7108c8f9c","4f839fabe80355bc","e769d7796ca92538"]]},{"id":"e40f4f216d871f04","type":"join","z":"f8535fdf67d273c2","name":"","mode":"custom","build":"merged","property":"payload","propertyType":"msg","key":"topic","joiner":"","joinerType":"str","accumulate":false,"timeout":"","count":"","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":350,"y":160,"wires":[["66221b9114fd8b9c","708e096eb9ae2133"]]},{"id":"52f9724683855c3f","type":"function","z":"f8535fdf67d273c2","name":"Reset","func":"flow.set('temp_min', 100);\nflow.set('temp_max', -100);\nflow.set('pressure_min', 5000);\nflow.set('pressure_max', -5000);\nflow.set('humidity_min', 100);\nflow.set('humidity_max', -100);\nflow.set('voc_min', 5000000);\nflow.set('voc_max', -5000000);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":240,"wires":[["66221b9114fd8b9c"]]},{"id":"1212f1a329356472","type":"split","z":"f8535fdf67d273c2","name":"","splt":",","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":150,"y":160,"wires":[["cc645c236b588053"]]},{"id":"cc645c236b588053","type":"json","z":"f8535fdf67d273c2","name":"","property":"payload","action":"obj","pretty":false,"x":150,"y":200,"wires":[["e40f4f216d871f04"]]},{"id":"8698adccd600fe6d","type":"inject","z":"f8535fdf67d273c2","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":170,"y":100,"wires":[["02ee370969a0b1a4"]]},{"id":"3de0fc5b92561b75","type":"file","z":"f8535fdf67d273c2","name":"BKP","filename":"BME680 Data.txt","appendNewline":true,"createDir":true,"overwriteFile":"false","encoding":"none","x":590,"y":100,"wires":[[]]},{"id":"572352ca7bc0a381","type":"debug","z":"f8535fdf67d273c2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":950,"y":80,"wires":[]},{"id":"61edc201f4510533","type":"ui_button","z":"f8535fdf67d273c2","name":"","group":"e66437e4.1a68e8","order":3,"width":6,"height":1,"passthru":false,"label":"Reset","tooltip":"","color":"","bgcolor":"","className":"","icon":"","payload":"","payloadType":"str","topic":"","topicType":"str","x":150,"y":240,"wires":[["52f9724683855c3f"]]},{"id":"4f839fabe80355bc","type":"ui_gauge","z":"f8535fdf67d273c2","name":"Pressure Gauge","group":"b4c4e00d.cbf16","order":1,"width":3,"height":4,"gtype":"gage","title":"","label":"Pressure HPA","format":"{{msg.payload.Pressure_HPA}}","min":0,"max":"1500","colors":["#00b500","#e6e600","#ca3838"],"seg1":"500","seg2":"1000","className":"","x":1210,"y":200,"wires":[]},{"id":"44bba037c3a47aa4","type":"ui_chart","z":"f8535fdf67d273c2","name":"Pressure Chart (HPA)","group":"b4c4e00d.cbf16","order":2,"width":11,"height":4,"label":"","chartType":"line","legend":"false","xformat":"auto","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":"12","removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#fd0006","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":1220,"y":160,"wires":[[]]},{"id":"e769d7796ca92538","type":"ui_template","z":"f8535fdf67d273c2","group":"b4c4e00d.cbf16","name":"Pressure max and min","order":3,"width":14,"height":1,"format":"<div layout=\"row\" layout-align=\"start center\">\n  <span flex>&emsp;&emsp;&emsp;&emsp;Min (HPA):&emsp;<span style=\"color: green\">{{msg.pressure.min}}</span>\n  &emsp;&emsp;Max:&emsp;<span flex style=\"color: red\">{{msg.pressure.max}}</span></span>\n</div>","storeOutMessages":false,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","x":1220,"y":240,"wires":[[]]},{"id":"02ee370969a0b1a4","type":"pythonshell in","z":"f8535fdf67d273c2","name":"BME680 Reader","pyfile":"/home/weatherstaff/bme680/examples/BMESCRIPT.py","virtualenv":"","continuous":true,"stdInData":true,"x":410,"y":100,"wires":[["1212f1a329356472","3de0fc5b92561b75"]]},{"id":"5d53df1e84a90d89","type":"ui_text_input","z":"f8535fdf67d273c2","name":"","label":"Set Altimeter","tooltip":"hPa","group":"556809bfb29d0453","order":3,"width":0,"height":0,"passthru":true,"mode":"number","delay":300,"topic":"altimeter","sendOnBlur":true,"className":"","topicType":"flow","x":170,"y":280,"wires":[["58352bc042d7301d"]]},{"id":"58352bc042d7301d","type":"change","z":"f8535fdf67d273c2","name":"flow.alt","rules":[{"t":"set","p":"altimeter","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":280,"wires":[[]]},{"id":"708e096eb9ae2133","type":"function","z":"f8535fdf67d273c2","name":"","func":"var pressure=msg.Pressure_HPA ;\nvar altimeter=flow.altimeter ;\n\nfunction altitude(altimeter, pressure) {\n  result = (altimeter - pressure) * 10000\n\n   return result\n}\n\nmsg.payload = altitude(altimeter, pressure)\n\nreturn msg\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":960,"y":120,"wires":[["572352ca7bc0a381","0e22fbb684a689d0","f235df18f02ca23c"]]},{"id":"f235df18f02ca23c","type":"ui_gauge","z":"f8535fdf67d273c2","name":"Altitude Gauge","group":"556809bfb29d0453","order":1,"width":3,"height":4,"gtype":"gage","title":"","label":"units","format":"{{value}}","min":0,"max":10,"colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","className":"","x":1200,"y":80,"wires":[]},{"id":"0e22fbb684a689d0","type":"ui_chart","z":"f8535fdf67d273c2","name":"Altitude Chart","group":"556809bfb29d0453","order":2,"width":11,"height":4,"label":"","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"useUTC":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"outputs":1,"useDifferentColor":false,"className":"","x":1200,"y":120,"wires":[[]]},{"id":"e66437e4.1a68e8","type":"ui_group","name":"Buttons","tab":"6c90afc.b3623d","order":6,"disp":false,"width":"14","collapse":false,"className":""},{"id":"b4c4e00d.cbf16","type":"ui_group","name":"Pressure (HPA)","tab":"6c90afc.b3623d","order":2,"disp":true,"width":14,"collapse":false},{"id":"556809bfb29d0453","type":"ui_group","name":"Altitude","tab":"6c90afc.b3623d","order":5,"disp":true,"width":14,"collapse":false,"className":""},{"id":"6c90afc.b3623d","type":"ui_tab","name":"BME688","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

Why are you using node-red-contrib-pythonshell and not node-red-contrib-bme680-rpi?

You function node you can

msg.payload.altitude = (flow.get("altimeter") - msg.Pressure_HPA) * 1000;

return msg;

Also post the json object you get out pythonshell, then it is easy for us to test your flow.

Sorry for the delayed response, this is a project I have been working on and off of for around 4 years. That node did not exist at the time and I do not want to rewrite the entire project for one feature that is not a necessity. The flow I have posted is only the relevant parts, and the full flow is much bigger.

Here is the code for the pythonshell, Which comes from an older version of pimoroni's bme680 code:

   /home/weatherstaff/bme680/examples/BMESCRIPT.py

#!/usr/bin/env python

import bme680
import time

try:
    sensor = bme680.BME680(bme680.I2C_ADDR_SECONDARY)
except IOError:
    sensor = bme680.BME680(bme680.I2C_ADDR_PRIMARY)

# These oversampling settings can be tweaked to
# change the balance between accuracy and noise in
# the data.

sensor.set_humidity_oversample(bme680.OS_2X)
sensor.set_pressure_oversample(bme680.OS_4X)
sensor.set_temperature_oversample(bme680.OS_8X)
sensor.set_filter(bme680.FILTER_SIZE_3)
sensor.set_gas_status(bme680.ENABLE_GAS_MEAS)

#print('\n\nInitial reading:')
#for name in dir(sensor.data):
#    value = getattr(sensor.data, name)
#    if not name.startswith('_'):
#        print('{}: {}'.format(name, value))

sensor.set_gas_heater_temperature(320)
sensor.set_gas_heater_duration(150)
sensor.select_gas_heater_profile(0)

# Up to 10 heater profiles can be configured, each
# with their own temperature and duration.
# sensor.set_gas_heater_profile(200, 150, nb_profile=1)
# sensor.select_gas_heater_profile(1)

#print('\n\nPolling:')
try:
    while True:
        if sensor.get_sensor_data():
            output = '{{"Temperature_oC":{0:.2f}}},{{"Pressure_HPA":{1:.2f}}},{>
                sensor.data.temperature,
                sensor.data.pressure,
                sensor.data.humidity)
            #output = '{0:.2f} C,{1:.2f} hPa,{2:.2f} %RH'.format(
                #sensor.data.temperature,
                #sensor.data.pressure,
                #sensor.data.humidity)

            if sensor.data.heat_stable:
                print('{0},{{"Resistance_Ohms":{1}}}'.format(
                    output,
                    sensor.data.gas_resistance))
                #print('{0},{1} Ohms'.format(
                #    output,
                #    sensor.data.gas_resistance))
            else:
                print(output)

        time.sleep(10)

except KeyboardInterrupt:
    pass

Here is the output of the pythonshell:

{"payload":"{\"Temperature_oC\":27.43},{\"Pressure_HPA\":994.72},{\"RelativeHumidity_percent\":39.76},{\"Resistance_Ohms\":665151.023059435}\n","_msgid":"35f8602c4daab435"}

What do you get if you feed that output into a JSON node?