Particulate matter sensor does not push data to Influxdb

Describe the error

What I have:
1.ESP8266

Particulate matter sensor

ID: 5234708 (dc4f224fe014)
Firmware version: R_2022-137/EN (Jul 3 2023)

Firmware version

R_2022-137
ST:1
SDK:2.2.2-dev(38a443e)
Core:2.7.3-3-g2843a5ac=20703003
lwIP:STABLE-2_1_2_RELEASE
glue:1.2-30-g92add50
BearSSL:5c771be

  1. SDS011
    3.BME280
  2. Own database influxdb version influxdb: 2.0

Problem:
I don’t see any data coming into the influx db database from the ESP8266

For playback
Steps to reproduce the behavior:

(I log in using my login password successfully through the web interface)
influxdb version:2.0
ifluxdb authorization data:
login: sysadmin
password: sysadmin
database: sysadmin
ip: 17.0.0.200
port: 8086

  1. Port 8086 is open on the server
  2. The database has a sysadmin database
  3. Authorization is allowed from the sysadmin user (the user has full access rights)
  4. In ESP8266 configuration parameters
    The Send data to influxdb checkbox is checked below what data I enter

server: 17.0.0.200
path: /write?db=sysadmin
user: sysadmin
password: sysadmin
measurement: feinstaub

Expected Behavior

The goal is to get data from ESP8266 into the influxdb database,
to later display graphs in grafana

Screenshots




Additional context
Please help me solve this problem,
Perhaps I’m not writing the request to transfer data to the database correctly?

path: /write?db=sysadmin

if so, which one is correct?
I tried to find information on the Internet, but didn’t find anything useful.
I see that the problem is not only with me and other users. Please help me solve this problem
Thanks for understanding

The settings look correct for connecting to InfluxDB v1 instances. InfluxDB v2 authorization changed significantly but according to Manually upgrade from InfluxDB 1.x to 2.7 | InfluxDB OSS v2 Documentation it is possible to setup V1 compatible authorizations which should enable 1.x clients (like the sensor) to connect and write to InfluxDB 2.x.

Indeed, the user @Phaze-III right, on version influx influxdb:1.8 there is an attempt to authorize the database.

Please note who will configure the influxdb version: 1.8.
Need to

  1. go to influx console,

command →

influx

  1. Create a user with a password and full rights, in my case the user is: sysadmin
    password: sysadmin full rights.

Command →

CREATE USER “sysadmin” WITH PASSWORD ‘sysadmin’ WITH ALL PRIVILEGES

  1. Create a database with the name: sysadmin

Command →

CREATE DATABASE sysadmin

If you have a problem with this task, write here, I will try to help you. Thanks again @Phaze-III

@caduceus.crow : if I understand your last post correctly, does it mean that you have went back to influxdb 1.8 in order to be able to connect, or did you actually manage to connect to influxdb 2.x?

Hello <3 @freibadschwimmer

Perhaps I didn’t spend enough time on influxdb 2.x. And that’s why I couldn’t get data from there. That’s why I installed influxdb 1.8.

I have a similar issue - thanks for offering help!
Firmware version: NRZ-2020-133/EN (Nov 29 2020)
InfluxDB shell version: 1.6.7~rc0

I created a separate database for airrohr, and Grafana says: “datasource is working. 0 measurements found”

airrohr and Influx are not in the same subnet. Firewall rules should be okay, but how to validate?

These are my settings:
image

There are InfluxDB errors obviously, but no clue which kind:

Also debug log gives no hint. Any ideas?

Hello.

  1. what you need to do is check if the INFLUX DB database port is accessible, namely 8086.

ATTENTION: This must be done from the subnet where your sensor is located.

This is an example so you can understand:

For example, your sensor in NETWORK
192.168.10.0/24

The sensor has the address: 192.168.10.10

PC: 192.168.10.20

You need to run TELNET from a PC whose address is 192.168.10.20

Launch a command prompt and run

telnet 192.168.6.31:8086

This is necessary in order to find out whether there is a connection between subnets,

and can your sensor reach the INFLUX DB server (192.168.6.31:8086)

  1. View INFLUX DB server logs. If the connection is between subnets,
    You should see information in the INFLUX DB Server logs indicating that data is being received.

Please try what I recommended and write an answer,

If it doesn’t work out, write to me, I will help you personally!

Hi @caduceus.crow thanks for your reply!

To confirm, I unplugged my airrohr and gave its IP address to my notebook. As expected, Influx is available in this setup (via Telnet, as suggested). This might prove that firewall config is okay. However it is no proof that Airrohr is able to communicate. It might have an issue with the different subnet, or it might have trouble with its slightly unusual /20 subnet. Unfortunately, there’s no shell on airrohr to check from there directly. I wonder if I should do some packet tracing behind the accesspoint…

I also tried to access Influx logs via sudo journalctl -u influxdb.service As expected, there are no airrohr related entries.
Also airrohr logs aren’t giving any hints on why this fails. On “min info”, we can see this:

## Sending to sensor.community - BME280
Succeeded - api.sensor.community
## Sending to madavi.de: 
Succeeded - api-rrd.madavi.de
## Sending to custom influx db: 
Time for Sending (ms): 564
ws: config page ...
begin webserver_config_body_get ...
ws: root ...

On “max info”, I won’t see any entries regarding Influx.

Thanks for your help!

Hello,

I am ready to help you personally, leave your contact information for feedback (mail or telegram), I will contact you and try to help you. <3

Okay, as always it’s easy when you’re looking back.

  • I had mixed up IP addresses, so airrohr was sending to the wrong IP address
  • It seems it took a while until data turned up in Grafana. With a little more patience, it simply worked.

    Thank you! :heart:

I was able to get influxdb v2 working by following the this comment on github.

Basically, the sensor firmware tries sending the data using v1 of the influxdb api so you have to make a user that uses the v1 auth. Like this:

$ influx v1 auth create --username 'username' --write-bucket 'bucket-id' --password 'password' --org 'Org Name'
$ influx v1 dbrp create --bucket-id (from above) --db feinstaub --org 'Org Name' --default --rp feinstaub

apuls, GitHub

Here’s my sensor configuration and how it looks in influxdb.

(I can only post one image for now, as I’m new…)

Happy to help anyone wanting to get it working with influxdb v2 :slight_smile:

How it looks in influxdb

1 Like

And I got it working how I wanted it to. Again, happy to help anyone migrate to influxdb v2. It was just a matter of a simple docker compose file, the aforementioned workaround with the v1 auth, and setting the sensor to point to the right api.

1 Like

Hi, how can I create such a chart in influxdb v2? Is there a config file that you could send me as an example?

Sure, here’s my dashboard config file (I can’t upload the .json file, so I’ll try and post it here). I think you can just import it and change the queries to represent your sensor’s id.

The main.json file
[
  {
    "apiVersion": "influxdata.com/v2alpha1",
    "kind": "Dashboard",
    "metadata": {
      "name": "elastic-shtern-433001"
    },
    "spec": {
      "charts": [
        {
          "axes": [
            {
              "base": "10",
              "name": "x",
              "scale": "linear"
            },
            {
              "base": "10",
              "name": "y",
              "scale": "linear",
              "suffix": "°C"
            }
          ],
          "colorizeRows": true,
          "colors": [
            {
              "id": "CPf9stCk76p_J_BoXTHF_",
              "name": "Nineteen Eighty Four",
              "type": "scale",
              "hex": "#31C0F6"
            },
            {
              "id": "l3oN_vVowx4hW8z7HqlZ_",
              "name": "Nineteen Eighty Four",
              "type": "scale",
              "hex": "#A500A5"
            },
            {
              "id": "suIRCu3qDXlSbL6wYA2eK",
              "name": "Nineteen Eighty Four",
              "type": "scale",
              "hex": "#FF7E27"
            }
          ],
          "geom": "line",
          "height": 4,
          "hoverDimension": "auto",
          "kind": "Xy",
          "legendColorizeRows": true,
          "legendOpacity": 1,
          "legendOrientationThreshold": 100000000,
          "name": "24hr Temp",
          "opacity": 1,
          "orientationThreshold": 100000000,
          "position": "overlaid",
          "queries": [
            {
              "query": "from(bucket: \"influx\")\n  |> range(start: -24h, stop: v.timeRangeStop)\n  |> filter(fn: (r) => r[\"_measurement\"] == \"feinstaub\")\n  |> filter(fn: (r) => r[\"_field\"] == \"BME280_temperature\")\n  |> filter(fn: (r) => r[\"node\"] == \"esp8266-15514816\")\n  |> aggregateWindow(every: 3m, fn: mean, createEmpty: false)\n  |> yield(name: \"mean\")"
            }
          ],
          "staticLegend": {
            "colorizeRows": true,
            "opacity": 1,
            "orientationThreshold": 100000000,
            "widthRatio": 1
          },
          "width": 6,
          "widthRatio": 1,
          "xCol": "_time",
          "yCol": "_value"
        },
        {
          "colors": [
            {
              "id": "0",
              "name": "pool",
              "type": "min",
              "hex": "#22ADF6",
              "value": 20
            },
            {
              "id": "TA9HqluhULEZP_tLBEfYA",
              "name": "honeydew",
              "type": "threshold",
              "hex": "#7CE490",
              "value": 22
            },
            {
              "id": "sjZO0p4Z3lMdMvWrFkosS",
              "name": "thunder",
              "type": "threshold",
              "hex": "#FFD255",
              "value": 27
            },
            {
              "id": "-S9MBJwj1_-KODoMKN86Z",
              "name": "pineapple",
              "type": "threshold",
              "hex": "#FFB94A",
              "value": 28.5
            },
            {
              "id": "jSHrGf1WhofiqzJlGJn9U",
              "name": "tiger",
              "type": "threshold",
              "hex": "#F48D38",
              "value": 31
            },
            {
              "id": "CT7aHfsgBKHtZ_xG8t-PH",
              "name": "curacao",
              "type": "threshold",
              "hex": "#F95F53",
              "value": 33
            },
            {
              "id": "1",
              "name": "comet",
              "type": "max",
              "hex": "#9394FF",
              "value": 35
            }
          ],
          "decimalPlaces": 2,
          "height": 5,
          "kind": "Gauge",
          "name": "temp gauge",
          "queries": [
            {
              "query": "from(bucket: \"influx\")\n  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |> filter(fn: (r) => r[\"_measurement\"] == \"feinstaub\")\n  |> filter(fn: (r) => r[\"_field\"] == \"BME280_temperature\")\n  |> filter(fn: (r) => r[\"node\"] == \"esp8266-15514816\")\n  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n  |> yield(name: \"mean\")"
            }
          ],
          "staticLegend": {},
          "suffix": "°C",
          "width": 3,
          "yPos": 4
        },
        {
          "axes": [
            {
              "name": "x",
              "scale": "linear"
            },
            {
              "name": "y",
              "scale": "linear",
              "suffix": "%"
            }
          ],
          "colorizeRows": true,
          "colors": [
            {
              "id": "EclyiLoTHdQDfhpQR2NyT",
              "name": "Cthulhu",
              "type": "scale",
              "hex": "#FDC44F"
            },
            {
              "id": "BZ-D8AreuWzQqOtndOfge",
              "name": "Cthulhu",
              "type": "scale",
              "hex": "#007C76"
            },
            {
              "id": "6j-eax57khgmTbE7AHg7_",
              "name": "Cthulhu",
              "type": "scale",
              "hex": "#8983FF"
            }
          ],
          "geom": "monotoneX",
          "height": 5,
          "heightRatio": 0.11,
          "hoverDimension": "xy",
          "kind": "Band",
          "legendColorizeRows": true,
          "legendOpacity": 1,
          "legendOrientationThreshold": -1,
          "mainColumn": "mean",
          "name": "Last 2 days humidity",
          "opacity": 1,
          "orientationThreshold": 100000000,
          "queries": [
            {
              "query": "import \"math\"\nimport \"date\"\n\nfrom(bucket: \"influx\")\n  |> range(start: -2d, stop: date.truncate(t: now(), unit:15m))\n  |> filter(fn: (r) => r[\"_measurement\"] == \"feinstaub\")\n  |> filter(fn: (r) => r[\"_field\"] ==  \"BME280_humidity\")\n  |> filter(fn: (r) => r[\"node\"] == \"esp8266-15514816\")\n  |> aggregateWindow(every: 5m, fn: mean, createEmpty: false)\n  |> timeShift(duration: -15m)\n  |> yield(name: \"mean\")"
            }
          ],
          "staticLegend": {
            "colorizeRows": true,
            "heightRatio": 0.11,
            "opacity": 1,
            "orientationThreshold": 100000000,
            "widthRatio": 1
          },
          "width": 6,
          "widthRatio": 1,
          "xCol": "_time",
          "yCol": "_value",
          "yPos": 9
        },
        {
          "colors": [
            {
              "id": "0",
              "name": "fire",
              "type": "min",
              "hex": "#DC4E58"
            },
            {
              "id": "TA9HqluhULEZP_tLBEfYA",
              "name": "honeydew",
              "type": "threshold",
              "hex": "#7CE490",
              "value": 40
            },
            {
              "id": "cJQswBeD1cX5gRH_GKkdm",
              "name": "ocean",
              "type": "threshold",
              "hex": "#4591ED",
              "value": 60
            },
            {
              "id": "1",
              "name": "ocean",
              "type": "max",
              "hex": "#4591ED",
              "value": 100
            }
          ],
          "decimalPlaces": 0,
          "height": 5,
          "kind": "Gauge",
          "name": "humidity gauge",
          "queries": [
            {
              "query": "from(bucket: \"influx\")\n  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |> filter(fn: (r) => r[\"_measurement\"] == \"feinstaub\")\n  |> filter(fn: (r) => r[\"_field\"] == \"BME280_humidity\")\n  |> filter(fn: (r) => r[\"node\"] == \"esp8266-15514816\")\n  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n  |> yield(name: \"mean\")"
            }
          ],
          "staticLegend": {},
          "suffix": "%",
          "width": 3,
          "xPos": 3,
          "yPos": 4
        },
        {
          "axes": [
            {
              "base": "10",
              "name": "x",
              "scale": "linear"
            },
            {
              "base": "10",
              "name": "y",
              "scale": "linear",
              "suffix": "μg/m³"
            }
          ],
          "colorizeRows": true,
          "colors": [
            {
              "id": "CPf9stCk76p_J_BoXTHF_",
              "name": "Nineteen Eighty Four",
              "type": "scale",
              "hex": "#31C0F6"
            },
            {
              "id": "l3oN_vVowx4hW8z7HqlZ_",
              "name": "Nineteen Eighty Four",
              "type": "scale",
              "hex": "#A500A5"
            },
            {
              "id": "suIRCu3qDXlSbL6wYA2eK",
              "name": "Nineteen Eighty Four",
              "type": "scale",
              "hex": "#FF7E27"
            }
          ],
          "geom": "line",
          "height": 4,
          "hoverDimension": "auto",
          "kind": "Xy",
          "legendColorizeRows": true,
          "legendOpacity": 1,
          "legendOrientationThreshold": 100000000,
          "name": "24hr PM",
          "opacity": 1,
          "orientationThreshold": 100000000,
          "position": "overlaid",
          "queries": [
            {
              "query": "from(bucket: \"influx\")\n  |> range(start: -24h, stop: v.timeRangeStop)\n  |> filter(fn: (r) => r[\"_measurement\"] == \"feinstaub\")\n  |> filter(fn: (r) => r[\"_field\"] == \"SDS_P1\" or r[\"_field\"] == \"SDS_P2\")\n  |> filter(fn: (r) => r[\"node\"] == \"esp8266-15514816\")\n  |> aggregateWindow(every: 3m, fn: mean, createEmpty: false)\n  |> yield(name: \"mean\")"
            }
          ],
          "staticLegend": {
            "colorizeRows": true,
            "opacity": 1,
            "orientationThreshold": 100000000,
            "widthRatio": 1
          },
          "width": 6,
          "widthRatio": 1,
          "xCol": "_time",
          "xPos": 6,
          "yCol": "_value"
        },
        {
          "colors": [
            {
              "id": "base",
              "name": "laser",
              "type": "text",
              "hex": "#00C9FF"
            }
          ],
          "decimalPlaces": 2,
          "height": 1,
          "kind": "Single_Stat",
          "name": "Current Temp",
          "queries": [
            {
              "query": "from(bucket: \"influx\")\n  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |> filter(fn: (r) => r[\"_measurement\"] == \"feinstaub\")\n  |> filter(fn: (r) => r[\"_field\"] == \"BME280_temperature\")\n  |> filter(fn: (r) => r[\"node\"] == \"esp8266-15514816\")\n  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n  |> yield(name: \"mean\")"
            }
          ],
          "staticLegend": {},
          "suffix": "°C",
          "width": 3,
          "xPos": 6,
          "yPos": 4
        },
        {
          "colors": [
            {
              "id": "0",
              "name": "honeydew",
              "type": "min",
              "hex": "#7CE490"
            },
            {
              "id": "1",
              "name": "curacao",
              "type": "max",
              "hex": "#F95F53",
              "value": 15
            }
          ],
          "decimalPlaces": 2,
          "height": 4,
          "kind": "Gauge",
          "name": "PM-10 Air Quality Gauge",
          "prefix": "   ",
          "queries": [
            {
              "query": "from(bucket: \"influx\")\n  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |> filter(fn: (r) => r[\"_measurement\"] == \"feinstaub\")\n  |> filter(fn: (r) => r[\"_field\"] == \"SDS_P1\")\n  |> filter(fn: (r) => r[\"node\"] == \"esp8266-15514816\")\n  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n  |> yield(name: \"mean\")"
            }
          ],
          "staticLegend": {},
          "suffix": "μg/m³",
          "width": 3,
          "xPos": 6,
          "yPos": 5
        },
        {
          "axes": [
            {
              "name": "x",
              "scale": "linear"
            },
            {
              "name": "y",
              "scale": "linear",
              "suffix": "°C"
            }
          ],
          "colorizeRows": true,
          "colors": [
            {
              "id": "CWfM8KSk0KcJAoLDskliB",
              "name": "Nineteen Eighty Four",
              "type": "scale",
              "hex": "#31C0F6"
            },
            {
              "id": "RFJ2YvTqJpWNekKgVoFP-",
              "name": "Nineteen Eighty Four",
              "type": "scale",
              "hex": "#A500A5"
            },
            {
              "id": "4_LFQM31KEvV4uJI0sAor",
              "name": "Nineteen Eighty Four",
              "type": "scale",
              "hex": "#FF7E27"
            }
          ],
          "geom": "line",
          "height": 5,
          "hoverDimension": "auto",
          "kind": "Band",
          "legendColorizeRows": true,
          "legendOpacity": 1,
          "legendOrientationThreshold": 100000000,
          "mainColumn": "mean",
          "name": "Last 7 days temp",
          "opacity": 1,
          "orientationThreshold": 100000000,
          "queries": [
            {
              "query": "import \"math\"\nimport \"date\"\n\nfrom(bucket: \"influx\")\n  |> range(start: -7d, stop: date.truncate(t: now(), unit:30m))\n  |> filter(fn: (r) => r[\"_measurement\"] == \"feinstaub\")\n  |> filter(fn: (r) => r[\"_field\"] == \"BME280_temperature\")\n  |> filter(fn: (r) => r[\"node\"] == \"esp8266-15514816\")\n  |> aggregateWindow(every: 30m, fn: mean, createEmpty: false)\n  |> map(fn: (r) => ({r with _value: math.round(x: (r._value * 10.0)) / 10.0}))\n  |> timeShift(duration: -30m)\n  |> yield(name: \"mean\")"
            }
          ],
          "staticLegend": {
            "colorizeRows": true,
            "opacity": 1,
            "orientationThreshold": 100000000,
            "widthRatio": 1
          },
          "width": 6,
          "widthRatio": 1,
          "xCol": "_time",
          "xPos": 6,
          "yCol": "_value",
          "yPos": 9
        },
        {
          "colors": [
            {
              "id": "base",
              "name": "laser",
              "type": "text",
              "hex": "#00C9FF"
            }
          ],
          "decimalPlaces": 2,
          "height": 1,
          "kind": "Single_Stat",
          "name": "Current Humidity",
          "queries": [
            {
              "query": "from(bucket: \"influx\")\n  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |> filter(fn: (r) => r[\"_measurement\"] == \"feinstaub\")\n  |> filter(fn: (r) => r[\"_field\"] == \"BME280_humidity\")\n  |> filter(fn: (r) => r[\"node\"] == \"esp8266-15514816\")\n  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n  |> yield(name: \"mean\")"
            }
          ],
          "staticLegend": {},
          "suffix": "%",
          "width": 3,
          "xPos": 9,
          "yPos": 4
        },
        {
          "colors": [
            {
              "id": "0",
              "name": "honeydew",
              "type": "min",
              "hex": "#7CE490"
            },
            {
              "id": "1",
              "name": "curacao",
              "type": "max",
              "hex": "#F95F53",
              "value": 5
            }
          ],
          "decimalPlaces": 2,
          "height": 4,
          "kind": "Gauge",
          "name": "PM-2.5 Air Quality Gauge",
          "prefix": "   ",
          "queries": [
            {
              "query": "from(bucket: \"influx\")\n  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |> filter(fn: (r) => r[\"_measurement\"] == \"feinstaub\")\n  |> filter(fn: (r) => r[\"_field\"] == \"SDS_P2\")\n  |> filter(fn: (r) => r[\"node\"] == \"esp8266-15514816\")\n  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n  |> yield(name: \"mean\")"
            }
          ],
          "staticLegend": {},
          "suffix": "μg/m³",
          "width": 3,
          "xPos": 9,
          "yPos": 5
        }
      ],
      "name": "Main"
    }
  }
]

Influxdb has a GUI that lets you add these charts, I think it calls it ‘cells’. All the charts were made using that, except for the last one.

The last one is a 7day temp chart, I use this query for it:

import "math"
import "date"

from(bucket: "influx")
  |> range(start: -7d, stop: date.truncate(t: now(), unit:30m))
  |> filter(fn: (r) => r["_measurement"] == "feinstaub")
  |> filter(fn: (r) => r["_field"] == "BME280_temperature")
  |> filter(fn: (r) => r["node"] == "esp8266-15514816")
  |> aggregateWindow(every: 30m, fn: mean, createEmpty: false)
  |> timeShift(duration: -30m)
  |> drop(columns: ["table", "result", "_measurement", "node", "_field", "_start", "_stop"])
  |> map(fn: (r) => ({r with _value: math.round(x: (r._value * 10.0)) / 10.0}))

Hope that helps!

1 Like

Thanks neurosense for your write up to use an InfluxDB v2.

It did help me upgrade to a new influxdb instance I host on a k8s cluster.

Here is my snippet (less copy paste…).

PASS=<some pass>
INFLUX_TOKEN=<a token with full access>

USER=some_username
ORG=some_org
BUCKET=some_bucket
BUCKET_ID=.... (you can fetch it from the UI)
DB=some_db
RETENTION_POLICY=some_name
HOST=https://influxdb.... (wherever your host is)

influx v1 auth create --host $HOST --username $USER --write-bucket $BUCKET_ID --password $PASS --org $ORG
influx v1 dbrp create --host $HOST --bucket-id $BUCKET_ID --db $DB --org $ORG --default --rp $RETENTION_POLICY

My 2 cents is also that you should not invest too much into graphing with InfluxDB itself.
Grafana is much better for that. I just switched my db so I have little data for now but here is how Grafana can look like:

It is very easy to tweak and it fetches the data from your InfluxDB.