API di caricamento dati e script di esempio

Il primo passaggio è ottenere un token dalla pagina della piattaforma dati.

Una volta che hai il tuo token, puoi utilizzare il seguente script per caricare i tuoi dati. Dopo aver caricato i dati della prima stazione, vai su aqicn.org/data-feed/verification/ per configurare le tue stazioni e verificare i dati caricati.

Piattaforme software supportate:

Forniamo il software pronto all'uso per queste 3 piattaforme:

  • Arduino: se disponi di una CPU Arduino, utilizza il software pronto all'uso disponibile su github.com all'indirizzo aqicn/gaia-a08-arduino.
  • Python: utilizza lo snippet di codice riportato di seguito
  • Riga di comando (CURL): utilizza lo snippet di codice riportato di seguito

Se non disponi di una stazione di monitoraggio e desideri averne una, controlla le nostre stazioni di monitoraggio della qualità dell'aria GAIA.

Se preferisci una stazione fai-da-te, controlla GAIA A08.


--

Codice di esempio (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) 

Codice di esempio (arricciatura)

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}]\ 
}'

Codice di esempio (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(); 
}

Opzioni API

Parameter Type Optional/Mandatory Explanations
token string mandatory

Ottieni il tuo token da aqicn.org/data-platform/token.

station
station.id string mandatory

ID stazione univoco: puoi selezionare qualsiasi nome con un massimo di 128 caratteri.
Questo nome viene utilizzato solo internamente per te. Nessun altro vedrà questo ID

station.name string optional

Nome della stazione - potrebbe essere ad esempio il nome del tuo edificio, il nome di una strada, il nome di un dipartimento universitario, il codice della tua stazione meteorologica personale.
Questo nome verrà utilizzato come suffisso per l'URL della tua stazione.

station.latitude float optional

Longitudine della tua stazione

station.longitude float optional

Longitudine della tua stazione

organization
org.website string optional

Se disponi di un sito Web con ulteriori informazioni sulla tua stazione/sensore, aggiungeremo questo collegamento sulla nostra mappa quando verrà utilizzato per vedere la tua stazione

org.name string optional

Se specifichi un sito web, questo "nome organizzazione" verrà associato al sito web.

readings
readings[*].specie string mandatory

Nome dell'inquinante che stai segnalando. Per i sensori di gas, utilizzare: "pm2.5", "pm10", "pm1.0", ... Per il sensore di gas, utilizzare: "co2", "no2", "o3", ... Per il sensore meteorologico, usa: "temp", "umidità", "pressione", "velocità del vento", "raffica di vento", "direzione del vento", ..
Puoi effettivamente usare qualsiasi nome di specie tu voglia. Una volta convalidata la tua stazione, i nomi verranno normalizzati nel nostro sistema.

readings[*].value float mandatory

Se il tuo sensore produce valori ogni secondo e carichi solo ogni minuto, questo valore dovrebbe essere la media di tutti i valori letti nell'ultimo minuto.

readings[*].unit string optional

Unità del valore. Ad esempio "mg/m3" per sensore polvere, ppb per sensori gas, C per sensore temperatura..

readings[*].time string optional

Data e Ora della lettura in formato ISO 8601

readings[*].min float optional

Se i valori di lettura si basano sulla media di più valori, ciò corrisponde al valore minimo di tutti i valori utilizzati per la media.

readings[*].max float optional

Se i valori di lettura si basano sulla media di più valori, ciò corrisponde al valore massimo di tutti i valori utilizzati per la media.

readings[*].median float optional

Se i valori di lettura si basano sulla media di più valori, ciò corrisponde al valore medio di tutti i valori utilizzati per la media.

readings[*].stddev float optional

Se i valori di lettura si basano sulla media di più valori, ciò corrisponde alla deviazione standard di tutti i valori utilizzati per la media.

readings[*].averaging float optional

Se i valori sopra indicati si basano sulla media di più valori, ciò corrisponde alla durata, in secondi, del periodo di media.
Ad esempio, utilizza 60 per i dati medi al minuto e 3600 per la media oraria.

Esempio 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-12-21T23:08:58+09:00","specie":"pm2.5", "value": 393.3, "unit":"mg/m3", "min":390.3, "max": 402.3, "stddev": 0.332},  
		{"time":"2024-12-21T23:08:58+09:00","specie":"pm10", "value": 109.3, "unit":"mg/m3"}, 
		{"time":"2024-12-21T23:08:58+09:00","specie":"co2", "value": 459.3, "unit":"ppb"}, 
		{"time":"2024-12-21T23:08:58+09:00","specie":"temp", "value": 26.8, "unit":"C"}, 
	] 
}

Esempio 2

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

Esempio di codice completo

Puoi utilizzare questo codice per la lettura continua da un sensore SDS e il caricamento ogni minuto: (script disponibile anche da 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) 
 

Conosci stazioni di controllo della qualità dell'aria nella tua zona?
perché non partecipi alla mappa con la tua stazione di misurazione della qualità dell'aria?

I nostri monitor della qualità dell'aria GAIA sono molto facili da configurare: hai solo bisogno di un punto di accesso WIFI e di un alimentatore compatibile con USB.

Una volta connesso, i livelli di inquinamento atmosferico in tempo reale sono immediatamente disponibili sulle mappe e tramite l'API.

La stazione viene fornita con un cavo di alimentazione impermeabile da 10 metri, un alimentatore USB, attrezzature di montaggio e un pannello solare opzionale.

Informazioni sulla misurazione della qualità dell'aria e dell'inquinamento:

Informazioni sui livelli di qualità dell'aria

- Valori dell'indice di qualità dell'aria (AQI).Livelli di preoccupazione per la salute
0 - 50 Buona La qualità dell'aria è considerata soddisfacente e l'inquinamento atmosferico presenta rischi minimi o nulli
51 -100 Moderato La qualità dell'aria è accettabile; tuttavia, per alcuni inquinanti può esserci un problema di salute moderato per un numero molto limitato di persone che sono insolitamente sensibili all'inquinamento atmosferico.
101-150 Malsano per gruppi sensibili I residenti appartenenti a gruppi sensibili (per patologie) possono avere effetti sulla salute. È improbabile che gli effetti siano seri per tutta la popolazione.
151-200 malsano Ognuno può iniziare a sperimentare effetti sulla salute; i membri di gruppi sensibili possono avere effetti sulla salute più gravi
201-300 Molto malsano Avvisi sulla salute delle condizioni di emergenza. È più probabile che l'intera popolazione sia colpita.
300+ Pericoloso Allerta salute: chiunque può essere soggetto a effetti piu gravi sulla propria salute

Per saperne di più sulla qualità dell'aria e sull'inquinamento, consulta l' argomento Qualità dell'aria di Wikipedia o la guida Airnow sulla qualità dell'aria e la tua salute .

Per consigli sanitari molto utili del dottor Richard Saint Cyr MD di Pechino, controlla il blog www.myhealthbeijing.com .


Avviso di utilizzo: Tutti i dati relativi alla qualità dell'aria non sono validati al momento della pubblicazione e, a causa dell'assicurazione della qualità, questi dati possono essere modificati, senza preavviso, in qualsiasi momento. Il World Air Quality Index progetto ha esercitato tutte le ragionevoli capacità e attenzione nella compilazione del contenuto di queste informazioni e in nessun caso il World Air Quality Index team di progetto o i suoi agenti sono responsabili in contratto, illecito o altro per qualsiasi perdita, danno o danno derivante direttamente o indirettamente dalla fornitura di questi dati.



Settings


Language Settings:


Temperature unit:
Celcius