Daten-Upload-API und Beispielskripts

Der erste Schritt besteht darin, ein Token von der Datenplattformseite abzurufen.

Sobald Sie Ihren eigenen Token haben, können Sie das folgende Skript verwenden, um Ihre Daten hochzuladen. Nachdem Sie Ihre ersten Stationsdaten hochgeladen haben, gehen Sie zu aqicn.org/data-feed/verification/, um Ihre Stationen zu konfigurieren und die hochgeladenen Daten zu überprüfen.

Unterstützte Softwareplattformen:

Wir bieten die gebrauchsfertige Software für diese drei Plattformen:

  • Arduino: Wenn Sie eine Arduino-CPU haben, verwenden Sie die gebrauchsfertige Software, die auf github.com unter aqicn/gaia-a08-arduino.
  • Python: Verwenden Sie den folgenden Codeausschnitt.
  • Befehlszeile (CURL): Verwenden Sie den folgenden Codeausschnitt

Wenn Sie keine Überwachungsstation haben und sich eine anschaffen möchten, sehen Sie sich unsere GAIA-Luftqualitätsüberwachungsstationen an.

Wenn Sie eine DIY-Station bevorzugen, sehen Sie sich GAIA A08 an.


--

Beispielcode (Python)

import requests  
 
# Sensor parameter   
sensorReadings = [   
	{'specie':'pm25', 'value': 393.3},  
	{'specie':'pm10', 'value': 109.3}  
] 
 
# Station parameter   
station = { 
	'id':		"station-001",  
	'location':  { 
		'latitude': 28.7501,  
		'longitude': 77.1177 
	} 
} 
 
# User parameter - get yours from https://aqicn.org/data-platform/token/ 
userToken = "dummy-token-for-test-purpose-only" 
 
# Then Upload the data  
params = {'station':station,'readings':sensorReadings,'token':userToken}  
request = requests.post( url = "https://aqicn.org/sensor/upload/",  json = params) 
#print(request.text) 
data = request.json()  
 
if data["status"]!="ok": 
	print("Something went wrong: %s" % data) 
else: 
	print("Data successfully posted: %s"%data) 

Beispielcode (Curl)

curl -X POST https://aqicn.org/sensor/upload -H 'Content-Type: application/json' --data '{\ 
"token": "dummy-token-for-test-purpose-only",\ 
"station": { "id": "station-001" },\ 
"readings": [{"specie":"pm2.5", "value": 393.3}]\ 
}'

Beispielcode (Arduino)

Check github.com/aqicn/gaia-a08-arduino for the full code.
#include <WiFi.h> 
#include <HTTPClient.h> 
#include <ArduinoJson.h> 
 
#define LATITUDE 28.7501 
#define LONGITUDE 77.1177 
 
void upload(float pm25_concentration, float pm10_concentration, const char * token) 
{ 
 
    static char stationID[32]; 
    uint64_t efuseMac = ESP.getEfuseMac(); 
    uint16_t chip = (uint16_t)(efuseMac >> 32); 
    snprintf(stationID, 32, "station-%x", chip); 
 
    doc["token"] = token; 
    doc["station"]["id"] = stationID; 
 
    doc["station"]["location"]["latitude"] = LATITUDE; 
    doc["station"]["location"]["longitude"] = LONGITUDE; 
 
    doc["readings"][0]["specie"] = "pm25"; 
    doc["readings"][0]["value"] = pm25_concentration; 
    doc["readings"][0]["unit"] = "µg/m3"; 
 
    doc["readings"][1]["specie"] = "pm10"; 
    doc["readings"][1]["value"] = pm10_concentration; 
    doc["readings"][1]["unit"] = "µg/m3"; 
 
    static char json_body[1024]; 
    serializeJson(doc, json_body); 
 
    HTTPClient http; 
    http.begin("https://aqicn.org/sensor/upload"); 
    http.addHeader("Content-Type", "application/json"); 
    int httpResponseCode = http.POST(json_body); 
 
    if (httpResponseCode > 0) 
    { 
 
        String response = http.getString(); 
        Serial.println(httpResponseCode); 
        Serial.println(response); 
    } 
    else 
    { 
 
        Serial.print("Error on sending POST: "); 
        Serial.println(httpResponseCode); 
    } 
 
    http.end(); 
}

API-Optionen

Parameter Type Optional/Mandatory Explanations
token string mandatory

Holen Sie sich Ihr eigenes Token von aqicn.org/data-platform/token.

station
station.id string mandatory

Eindeutige Stations-ID – Sie können einen beliebigen Namen mit maximal 128 Zeichen auswählen.
Dieser Name wird nur intern für Sie verwendet. Niemand sonst wird diese ID sehen

station.name string optional

Name der Station – könnte zum Beispiel der Name Ihres Gebäudes, der Name einer Straße, der Name einer Universitätsabteilung oder der Code Ihrer persönlichen Wetterstation sein.
Dieser Name wird als Suffix für Ihre Stations-URL verwendet.

station.latitude float optional

Längengrad Ihrer Station

station.longitude float optional

Längengrad Ihrer Station

organization
org.website string optional

Wenn Sie eine Website mit weiteren Informationen zu Ihrer Station/Ihrem Sensor haben, fügen wir diesen Link auf unserer Karte hinzu, wenn Sie ihn verwenden, um Ihre Station anzuzeigen

org.name string optional

Wenn Sie eine Website angeben, wird dieser „Organisationsname“ mit der Website verknüpft.

readings
readings[*].specie string mandatory

Name des Schadstoffs, den Sie melden. Für Gassensoren verwenden Sie: „pm2.5“, „pm10“, „pm1.0“, … Für Gassensoren verwenden Sie: „co2“, „no2“, „o3“, … Für Wettersensoren Verwenden Sie: „temp“, „feuchtigkeit“, „druck“, „windgeschwindigkeit“, „windböe“, „windrichtung“, ..
Sie können eigentlich jeden gewünschten Artennamen verwenden. Wenn Ihre Station validiert ist, werden die Namen in unserem System normalisiert.

readings[*].value float mandatory

Wenn Ihr Sensor jede Sekunde Werte erzeugt und Sie nur jede Minute hochladen, sollte dieser Wert der Durchschnitt aller in der letzten Minute gemessenen Werte sein.

readings[*].unit string optional

Einheit des Wertes. Beispiel: „mg/m3“ für Staubsensor, ppb für Gassensoren, C für Temperatursensor.

readings[*].time string optional

Datum und Uhrzeit der Lesung im ISO 8601-Format

readings[*].min float optional

Basieren die Messwerte auf der Mittelung mehrerer Werte, so entspricht dies dem Mindestwert aller für die Mittelung verwendeten Werte.

readings[*].max float optional

Basieren die Messwerte auf der Mittelung mehrerer Werte, so entspricht dies dem Maximalwert aller für die Mittelung verwendeten Werte.

readings[*].median float optional

Basieren die Messwerte auf der Mittelung mehrerer Werte, so entspricht dies dem Medianwert aller zur Mittelung herangezogenen Werte.

readings[*].stddev float optional

Basieren die Messwerte auf der Mittelung mehrerer Werte, so entspricht diese der Standardabweichung aller zur Mittelung herangezogenen Werte.

readings[*].averaging float optional

Basieren die oben genannten Werte auf der Mittelung mehrerer Werte, so entspricht dies der Dauer des Mittelungszeitraums in Sekunden.
Verwenden Sie beispielsweise 60 für einen Minutendurchschnitt und 3600 für einen Stundendurchschnitt.

Beispiel 1

{ 
	"token": "......", 
	"station": { 
		"id": "station-001", 
		"name": "HCPA Santa Cecília", 
		"latitude": 103.37893, 
		"longitude": 43.17108, 
	}, 
	"org": { 
		"website":"https://pacto.upsensor.com/", 
		"name":"Porto Ar Alegre", 
	}, 
	"readings": [ 
		{"time":"2024-04-27T19:25:29+09:00","specie":"pm2.5", "value": 393.3, "unit":"mg/m3", "min":390.3, "max": 402.3, "stddev": 0.332},  
		{"time":"2024-04-27T19:25:29+09:00","specie":"pm10", "value": 109.3, "unit":"mg/m3"}, 
		{"time":"2024-04-27T19:25:29+09:00","specie":"co2", "value": 459.3, "unit":"ppb"}, 
		{"time":"2024-04-27T19:25:29+09:00","specie":"temp", "value": 26.8, "unit":"C"}, 
	] 
}

Beispiel 2

{ 
	"token": "......", 
	"station": { 
		"id": "station-001", 
	}, 
	"readings": [ 
		{"specie":"pm2.5", "value": 393.3} 
	] 
}

Vollständiges Codebeispiel

Sie können diesen Code zum kontinuierlichen Lesen von einem SDS-Sensor und zum Hochladen jede Minute verwenden: (Skript auch verfügbar unter https://github .com/aqicn/sds-sensor-reader).

import requests 
import random 
import time 
import math 
import json 
import sys 
from serial import Serial 
 
LOCATION = {'latitude': 28.7501, 'longitude': 77.1177} 
TOKEN    = "dummy-token-for-test-purpose-only" 
SENSORID = "station-001" 
USBPORT  = "/dev/ttyUSB0" 
 
class SensorDataUploader: 
 
    def __init__(self, station, token): 
        self.token = token 
        self.station = station 
 
 
    def send(self,readings): 
 
        params = {'station':self.station,'readings':readings,'token':self.token}  
        print("Uploading: %s"%json.dumps(params, indent=4)) 
 
        request = requests.post( url = "https://aqicn.org/sensor/upload/",  json = params) 
        data = request.json()  
        if data["status"]!="ok": 
            print("Something went wrong: %s" % data) 
        else: 
            print("Data successfully posted: %s"%data) 
 
 
 
 
class Accumulator: 
 
    def __init__(self, name): 
        self.name = name 
        self.values = [] 
 
    def add(self,val): 
        self.values.append(val) 
 
    def count(self): 
        return len(self.values) 
 
    def reset(self): 
        self.values=[] 
 
    def min(self): 
        return self.values[0] 
 
    def max(self): 
        return self.values[len(self.values)-1] 
 
    def median(self): 
        return self.values[len(self.values)/2] 
 
    def mean(self): 
        return float(sum(self.values)) / len(self.values) 
 
    def stddev(self): 
        l = len(self.values) 
        mean = self.mean() 
        return math.sqrt(float(reduce(lambda x, y: x + y, map(lambda x: (x - mean) ** 2, self.values))) / l) 
 
 
    def summary(self): 
        self.values.sort() 
        return {"specie":self.name,'value':self.mean(),'min':self.min(),'max':self.max(),'median':self.median(), 'stddev':self.stddev()}  
 
 
 
class DummyReader: 
 
    def read( self ): 
 
        time.sleep(1.1) 
        return {"pm2.5":random.random()*10,"pm10":random.random()*10} 
 
 
class SDS011Reader: 
 
    def __init__(self, inport): 
        self.serial = Serial(port=inport,baudrate=9600) 
        self.values = [] 
        self.step = 0 
 
    def read( self ): 
 
        # time.sleep(1) 
        # return {"pm2.5":random.random()*100,"pm10":random.random()*100} 
 
        while self.serial.inWaiting()!=0: 
            v=ord(self.serial.read()) 
 
            if self.step ==0: 
                if v==170: 
                    self.step=1 
 
            elif self.step==1: 
                if v==192: 
                    self.values = [0,0,0,0,0,0,0] 
                    self.step=2 
                else: 
                    self.step=0 
 
            elif self.step>8: 
                self.step =0 
                pm25 = (self.values[0]+self.values[1]*256)/10 
                pm10 = (self.values[2]+self.values[3]*256)/10 
                return {"pm2.5":pm25,"pm10":pm10} 
 
            elif self.step>=2: 
                self.values[self.step-2]=v 
                self.step= self.step+1 
 
        return None 
 
 
 
def readAndUpload(sensor, uploader): 
 
    try: 
 
        while True: 
            accumulators = {} 
            startTime = time.time() 
 
            while time.time() < startTime+60: 
                values = sensor.read() 
                if values==None: 
                    continue 
 
                print("Reading [%2d]: %s"%(int(time.time()-startTime),values)) 
                for specie, value in values.items(): 
                    if not (specie in accumulators): 
                        accumulators[specie]=Accumulator(specie) 
                    accumulators[specie].add(value) 
 
 
            readings = [] 
            for specie, accumulator in accumulators.items(): 
                readings.append(accumulator.summary()) 
 
            if len(readings)>0: 
                uploader.send(readings) 
            else: 
                print("No value read from the sensor...") 
 
 
    except KeyboardInterrupt: 
        print "Bye" 
        sys.exit() 
 
 
 
print("Starting reading sensor "+SENSORID+" on port "+USBPORT) 
 
# Station parameter   
station = {'id':SENSORID, 'location':LOCATION} 
uploader = SensorDataUploader(station, TOKEN) 
 
sensor = SDS011Reader(USBPORT) 
# sensor = DummyReader() 
readAndUpload(sensor,uploader) 
 

Messen Sie die Luftqualität in Ihrer Nachbarschaft
Beteiligen Sie sich mit Ihrer eigenen Luftqualitätsüberwachungsstation

Der GAIA-Luftqualitätsmonitor misst mithilfe von Laserpartikelsensoren in Echtzeit die PM2,5- und PM10-Partikelverschmutzung, einen der schädlichsten Luftschadstoffe.

Die Einrichtung ist denkbar einfach: Es sind lediglich ein WLAN-Zugangspunkt und ein USB-kompatibles Netzteil erforderlich. Sobald die Verbindung hergestellt ist, sind Ihre Luftverschmutzungswerte in Echtzeit sofort auf unseren Karten verfügbar.

Die Station wird mit 10 Meter langen wasserdichten Stromkabeln, einem Netzteil, Montagezubehör und einem optionalen Solarpanel geliefert.

Über Messungen zur Luftqualität und Verschmutzung

Über die Luftqualitätsstufen

- Luftqualitätswerte (AQI)Stufen zur Bewertung der Gesundheitsgefährdung
0 - 50 Gut Die Luftqualität wird als zufriedenstellend angesehen, und die Luftverschmutzung birgt wenig oder kein Risiko.
51 -100 Mäßig Luftqualität ist akzeptabel; Bei einigen Schadstoffen kann es jedoch für eine sehr kleine Anzahl von Personen, die gegenüber Luftverschmutzung ungewöhnlich empfindlich sind, zu einem mäßigen Gesundheitsrisiko kommen.
101-150 Ungesund für sensible Gruppen Mitglieder von sensiblen Gruppen können gesundheitliche Auswirkungen haben. Die breite Öffentlichkeit wird wahrscheinlich nicht betroffen sein.
151-200 Ungesund Gesundheitliche Auswirkungen sind für jeden spürbar; für sensible Gruppen besteht möglicherweise ein ernstes gesundheitliches Risiko.
201-300 Sehr Ungesund Notfallwarnung vor Gesundheitsgefahren. Die Gesamtbevölkerung ist davon wahrscheinlich betroffen.
300+ Gefährlich Gesundheitswarnung: Jeder kann ernstere gesundheitliche Auswirkungen haben

Um mehr über Luftqualität und -verschmutzung zu erfahren, gehen Sie auf die Seite Luftverschmutzung (Wikipedia) oder den AIRNow Leitfaden für Luftqualität und Ihre Gesundheit der US-amerikanischen Umweltagentur.

Sehr nützliche Gesundheitsratschläge gibt der Pekinger Arzt Richard Saint Cyr MD, www.myhealthbeijing.com in seinem Blog.


Nutzungshinweis: Alle Luftqualitätsdaten sind zum Zeitpunkt der Veröffentlichung noch nicht verifiziert, und aufgrund der Qualitätssicherung können diese Daten jederzeit ohne vorherige Ankündigung geändert werden. Das World Air Quality Index Projekt hat alle angemessenen Fähigkeiten und Sorgfalt bei der Zusammenstellung der Inhalte dieser Informationen angewandt und unter keinen Umständen, vertraglich oder anderweitig haftet das , das World Air Quality Index Projektteam oder seine Agenten wegen unerlaubter Handlung oder anderweitig für Verluste, Verletzungen oder Schäden, die direkt oder indirekt aus der Bereitstellung dieser Daten entstehen.



Einstellungen


Spracheinstellungen:


Temperature unit:
Celcius