Question python code pushing sensor data

I would like to contribute to sensor community. Therefore I learned myself some python and looked into other scripts. But now I’m stuck at sending data to sensor.community. I must be missing something. Is somebody willing to help? My code:

Connects a SDS011 to a Raspberry Pi and send the results to sensor community

import time
import serial
import requests
import datetime
import json

Open serial connection to sensor

ser = serial.Serial(‘/dev/ttyUSB0’, baudrate=9600)

Your sensor’s coordinates

latitude = 12.34567890123
longitude = 1.23456789012

Format the coordinates as a string

location = str(latitude) + “,” + str(longitude)

while True:
# Put sensor in measurement mode (the 6th byte is 0x01 which means the sensor is in measuring mode)
ser.write(b’\xAA\xB4\x06\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x05\xAB’)
print(“Putting sensor in measurement mode”)

# Wait 60 seconds for sensor to warm up
print("Wait 1 minute for the sensor to warm up")
time.sleep(60)

# Read data from sensor
data = ser.read(10)

# Extract PM2.5 and PM10 values from data
pm25 = data[2] + data[3]/10
pm10 = data[4] + data[5]/10

# Print timestamp
now = datetime.datetime.now()
print("Timestamp: ", now)

# Print values on screen
print("PM2.5: ", pm25, "ug/m^3")
print("PM10: ", pm10, "ug/m^3")

# Put sensor in sleeping mode (the 6th byte is 0x00 which means the sensor is in sleeping mode)
ser.write(b'\xAA\xB4\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x05\xAB')
print("Putting sensor in sleeping mode")

# Sense data to sensor community server
api_endpoint = "https://api.sensor.community.info/v1/push-sensor-data/"
data = {
    "sensordatavalues": [
        {
            "value_type": "P1",
            "value": pm10
        },
        {
            "value_type": "P2",
            "value": pm25
        }
    ],
    "location": location,
    "sensor_id": 12345,
    "timestamp": now.isoformat()
}

max_retries = 5
retries = 0

while retries < max_retries:
    try:
        # Your code that you want to retry
        response = requests.post(api_endpoint, json=data)
        # If the request is successful, break out of the loop
        if response.status_code == 200:
            print("Data sent successfully")
            break
    except Exception as e:
        retries += 1
        # Wait for 5 seconds before retrying
        time.sleep(5)
        continue

# Take reading every 4 minutes including sensor warm-up (as only measurements within 5 minutes are shown on the map)
print("Waiting 3 minutes for next reading cycle")
time.sleep(180)

I don’t know why but the code-layout is not shown as planned, sorry.

I don’t think this is a valid url, it should be without .info at the end.

Thanks. This and adding the # or id in the results part and adding the UID as authentication did the trick. My working code is now:

import time
import serial
import requests
import datetime
import json

Open serial connection to sensor

ser = serial.Serial(‘/dev/ttyUSB0’, baudrate=9600)

Your sensor’s coordinates

latitude = 12.34567890123
longitude = 1.23456789012

Format the coordinates as a string

location = str(latitude) + “,” + str(longitude)

UID = “raspi-1234”

while True:
# Put sensor in measurement mode (the 6th byte is 0x01 which means the sensor is in measuring mode)
ser.write(b’\xAA\xB4\x06\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x05\xAB’)
print(“Putting sensor in measurement mode”)

# Wait 60 seconds for sensor to warm up
print("Wait 1 minute for the sensor to warm up and turn on the fan")
time.sleep(60)

# Read data from sensor
data = ser.read(10)

# Extract PM2.5 and PM10 values from data
pm25 = data[2] + data[3]/10
pm10 = data[4] + data[5]/10

# Print timestamp
now = datetime.datetime.now()
print("Timestamp: ", now)

# Print values on screen
print("PM2.5: ", pm25, "ug/m^3")
print("PM10: ", pm10, "ug/m^3")

# Put sensor in sleeping mode (the 6th byte is 0x00 which means the sensor is in sleeping mode)
ser.write(b'\xAA\xB4\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x05\xAB')
print("Putting sensor in sleeping mode which also turns off the fan")

# Sense data to sensor community server
api_endpoint = "https://api.sensor.community/v1/push-sensor-data/"
data = {
    "id": 12345,
    "sensordatavalues": [
        {
            "value_type": "P1",
            "value": pm10
        },
        {
            "value_type": "P2",
            "value": pm25
        }
    ],
    "location": location,
    "sensor_id": 12345,
    "timestamp": now.isoformat()
}

auth = {
"X-Sensor": UID
}

# Send data to API and print response
response = requests.post(api_endpoint, json=data, headers=auth)
print("Response:", response.text)

# Take reading every 10 minutes
print("Waiting 10 minutes (including warm-up) for next reading cycle")
time.sleep(540)

You know, you have to push data on both madavi and Sensor.Community ?
Do you add the header in the post request ?

Do Python automatically handles json like this ? There is no Serialize?

Should look like this:

import requests
import json

url = "https://api.sensor.community/v1/push-sensor-data/ "

payload = json.dumps({
  "software_version": "your_version",
  "sensordatavalues": [
    {
      "value_type": "P1",
      "value": "66.04"
    },
    {
      "value_type": "P2",
      "value": "53.32"
    }
  ]
})
headers = {
  'Content-Type': 'application/json',
  'X-Pin': '1',
  'X-Sensor': 'esp8266-12345678 '
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

Use Postman to test.

With the json lib, you should be able to fill the json easily.

The script posted above now works as wanted. Thanks

1 Like

Although, mmm, the fan doesn’t start again in measurement mode after the sleep mode

Solved it. I had to change the wake-up and or measurement command:
From
ser.write(b’\xAA\xB4\x06\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x05\xAB’)
To
ser.write(b’\xAA\xB4\x06\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x06\xAB’)
Found the solution on Issue after sleep function · Issue #21 · ricki-z/SDS011 · GitHub

And lastly I had to change the extraction of the bytes and the calculation to get the correct PM values:
# Start reading data from the sensor
data = ser.read(10)

# Extract high and low bytes for PM2.5 and PM10 from data
pm25_low = data[2]
pm25_high = data[3]
pm10_low = data[4]
pm10_high = data[5]

# Calculate PM2.5 and PM10 values
pm25 = ((pm25_high * 256) + pm25_low) / 10
pm10 = ((pm10_high * 256) + pm10_low) / 10
1 Like