Node-RED/Grafana "No measurement specified"


(Lachlan Etherton) #1

I have been trying to get Node-RED up and running for Grafana, however am coming into an issue where it tells me “No measurement specified”. I have already specified a payload byte as temperature in the TTN decoder, however I am unsure as to what is causing this issue. I did read this forum post, however am unable to resolve my problem. I do believe I need to add a function between ttn uplink and the influxdb nodes, however am unsure as to the Javascript I need to enter to make this work.

This is my uplink message, output by the msg debug:
msg : Object
object
app_id: “ttgo_cttg”
dev_id: “ttgo_cttg”
hardware_serial: “00DFBF1E9E708A1F”
port: 1
counter: 232
payload_raw: buffer[3]raw
0: 0x18
1: 0x0
2: 0x0
payload_fields: object
temperature: 24
metadata: object
time: “2018-12-18T06:09:37.344623318Z”
frequency: 917.4
modulation: “LORA”
data_rate: “SF7BW125”
airtime: 51456000
coding_rate: “4/5”
gateways: array[1]
payload: object
temperature: 24
_msgid: “de7688eb.e23468”

And my error is:
msg : string[24]
“No measurement specified”

An image of my current setup is as follows, which is identical to the one in the forum post I linked:
b6b2867e30aabe95d5b5e476e2daf003


#2

Here is what i do, but its a bit more complicated because i want to grab the info about which gateway got the data too, just to check if the situation changes over time.

I use a javascript node with this code:

var data = msg.payload_fields;
data.dev_id = msg.dev_id;
data.datarate = msg.metadata.data_rate;
var gateways = msg.metadata.gateways;
for(var i in gateways) {
    if(gateways[i].gtw_id !== null && gateways[i].gtw_id !== undefined) {
        data[i+"_gtw_id"] = gateways[i].gtw_id;
        data[i+"_rssi"] = gateways[i].rssi;
        data[i+"_latitude"] = gateways[i].latitude;
        data[i+"_longitude"] = gateways[i].longitude;
        if(gateways[i].altitude !== null && gateways[i].altitude !== undefined) {
            data[i+"_altitude"] = gateways[i].altitude;
        } else {
            data[i+"_altitude"] = 0; // Falls keine Altitude gesetzt wurde im Gateway
        }
    }
} 
return {
    payload: data
};

If you just want the temperature data you could go with this (i would include the device_id everytime, so you can seperate the data later if you got more than one device):

var data = msg.payload_fields;
data.dev_id = msg.dev_id;
return {
    payload: data
};

(Lachlan Etherton) #3

Thanks for the example code mate. Still trying to wrap my head around this stuff, so this will be of great assistance!


(Lachlan Etherton) #4

So, I’ve tried the last code section you suggested and I still have the same problem, being “No measurement specified”. Are there any other recommendations you have? Also, is there anything I have to do in in InfluxDB or Grafana other than creating a dashboard as shown in the second and third photos?

49%20am
07%20am
59%20am


#5

What is inside the influxdb node? You have to assign a “measurement” inside. In Grafana you will find this name for the measurement again if you click on “select measurement” (after the node-red is running).


(Lachlan Etherton) #7

Okay, so I’ve change the SELECT field(), which was blank to SELECT field(temperature) and if has started to work.

I do have a few question however.

  1. Do I need to update the FROM field as well and add temperature and if so why?
  2. Do I need to change the data source form default to influx, or is Grafana smart enough to work it out normally?

#8
  1. From “default” points to the default datasource (you can have more than one datasource in grafana but only one is the default one, so you have to set this to the right datasource if you got more than one).

  2. No clue, i always set the right type for the datasources (so influx for the influxdb) just to be sure…


(Lachlan Etherton) #9

Back to square one a bit,

So I’ve been changing a bit of the code on the TTN side. My current setup consist of two values, being temperature and humidity and now I am getting a new error in my debug console:

Error: A 400 Bad Request error occurred: {"error":"unable to parse 'temperature value=undefined': invalid boolean"}

Here is an output of my console (I’ve hidden the credentials):
14%20am

I have forced the value for temperature to be 350 which in the TTN Payload Format is decoded to be 35.
I have forced the value for humidity to be 750 which in the TTN Payload Format is decoded to be 75.

My raw hexadecimal payload is:
015E02EE

Where:

015E = 350
02EE = 750

In the Payload Format, the code is:

function Decoder(bytes) {
  var temperature = bytes[0]<<8 | bytes[1];
  var humidity = bytes[2]<<8 | bytes[3];
  return {
  temperature: temperature / 10,
  humidity: humidity / 10,
  };
}

I then have the following setup in Node-Red:
07%20am

My setup within the ttn event node is as follows:
44%20am
51%20am

In the msg debug nodes, I have set it as complete msg object

In Work Please! function, I have the following Javascript:

var temperature = msg.payload_fields;
return {
    payload: temperature
};

And in the influxdb out node I have set it as shown below:
01%20pm

Here is a screenshot of my console:
35%20pm

Even if I disable the humidity data from being transmitted, such that the payload is 015E0000 and also comment out the humidity lines in the Payload Format decoder, I get the same problem, so that is why I showed the above error with both temperature and humidity data being sent through.

Here is a screenshot of my TTN console when only transmitting temperature:
33%20pm

Here is screenshot of my Node-Red when only transmitting temperature:
10%20pm

From what I can see the payload is gibberish compare to the numbers I used to get when I scroll up and look my old screenshots. That makes me think that something funky is going on with the conversion, leading to these issues, but am unsure where it is occurring.

Do note that this error arrises with the influxdb node, but this may be because it is receiving the data it can’t read.

So my questions are:

  1. How do I fix this issue?
  2. How do I process two different values, such that within Grafana, they appear as two seperate graphs?

(Arjan) #10

It seems this uses the event topic? That is not giving you uplinks, hence also does not give you payload_fields; see the MQTT Data API documentation.

The fact the message only holds a single gateway_id also tells you it cannot be an uplink, as that might be received by multiple gateways. Actually, using an online decoder you’ll see that this is the AU915 initial ADR downlink, like discussed in your previous LMIC Library Always Does Unwanted Downlink.

Above, despite the name temperature this actually holds all payload fields. To explicitly get the values, use something like:

return {
    t: msg.payload_fields.temperature,
    h: msg.payload_fields.humidity 
};

Or, if you don’t want to change any names, simply:

return msg.payload_fields;

See What to do with the raw payload via MQTT? and Advantage of Base64 encoding in MQTT?

And given some problems people are having with authentication using the TTN Node-RED library, see also Node Red error 14, failed to connect, which you can avoid by using Node-RED’s built-in MQTT.

Beware that your Decoder does not support negative temperatures. And your sensor is probably not accurate enough for any decimal digit in humidity.


(Lachlan Etherton) #11

Thanks for the information @arjanvanb. Yeah, it’s meant to be ttn uplink. That’s solved that problem, so I’m getting “t” and “h” printed in the debug console successfully.

I’m now getting stuck with the measurement. I’ve tried to read up documentation, including the official article and I initially thought it was as simple as putting a value in the InfluxDB output node which is same in name to the variables in the function and it’d work, but it’s obviously not the case, nor does it seem consistent with other articles. This belief was based on previous experience when I only had a single value that I was transmitting.

At the moment my error, if I put “temperature” in the “Measurement” box my error is:

Error: A 400 Bad Request error occurred: {"error":"unable to parse 'temperature value=undefined': invalid boolean"}

This is the same if I enter, “t”, “h”, or “humidity” and is the one I mentioned before, but now it has become clearer it doesn’t have anything to do with the ten event and uplink mixup. From my understanding I need to specify the measurement which makes sense, however I am currently unsure as to how I do this.

The Javascript I currently have in the function is below, which you suggested:

return {
    t: msg.payload_fields.temperature,
    h: msg.payload_fields.humidity 
};

I have also set the number of outputs to 2.

If you scroll down in that article I linked above, it does show how they used measurements, however they only have a single value being returned, being msg.payload. Is this an alternative process to sending two values?

I have also found this Github article which shows the Javascript in the function which shows another way to go about doing this. They say that:

The receiving database needs to know
name of measurement

Which makes sense, however what is the measurement value it requires?

Going by this Github post, I tried the the following code in the function node:

var t = msg.payload_fields.temperature
var h = msg.payload_fields.humidity
return {
    temperature: t,
    humidity: h
}

It gave the values for temperature and humidity, however I still got the same error, no matter what if the measurement was “t”, “temperature”, “h” or “humidity”:

Error: A 400 Bad Request error occurred: {"error":"unable to parse 'temperature value=undefined': invalid boolean"}

Also, do I need to use 2 InfluxDB outputs for temperature and then humidity? I’ve seen this in a few examples I’ve looked up, so my current assumption is yes.


(Arjan) #12

In the example that Caspar gave you, it looks like:

It seems I was confused by var temperature = msg.payload_fields. So, I’d guess you need to return an object (denoted by { ... }) with a property/attribute payload, which itself is an object as well. The above would include everything that is already in your payload fields, so both temperature and humidity, plus the additional dev_id just for future reference if you have multiple devices.

If you want to rename (but probably not), you’d be using:

return {
    payload: {
        dev_id: msg.dev_id,
        t: msg.payload_fields.temperature,
        h: msg.payload_fields.humidity
    }
};

But I’d guess that Caspar’s version should do just fine.

You’re really just returning a single object (with multiple properties) so just one output should suffice.

I don’t have InfluxDB running at the moment, so I hope someone else understands the error you’re getting.


(Lachlan Etherton) #13

It works mate. Thanks for the clarification. I’ll be sure to remember this, so we don’t end up having to navigate through all the possible errors Node-RED could give again.

As for negative values I’m in Australia, so I probably won’t worry bout it. I have seen your post here however, so if I end up travelling into the alps, I’ll be sure to look into that. I had to check and the lowest on record the temperature in Adelaide is -0.4 degrees Celsius. Don’t worry, we compensate for that. Today’s temp was only in the low 40s. :face_with_thermometer:


(Arjan) #14

:slight_smile:

Fun fact, if you’d ever send that, then it’s probably sent as the integer -4, which in the default two’s complement encoding would be 0xFFFC or 0xFFFF FFFC in memory (when showing the memory contents as hexadecimal). When not handling negative values, you would then send 0xFFFC, which would decode back to 65532, hence 6,553.2 degrees. And you think 40 degrees is hot :wink:

If sent like that, then the following would handle that:

// Sign-extend to 32 bits to support negative values, by shifting 24 bits
// (16 too far) to the left, followed by a sign-propagating right shift:
var temperature = bytes[0]<<24>>16 | bytes[1];