API de carga de datos y scripts de muestra

El primer paso es obtener un token de la página de plataforma de datos.

Una vez que tenga su propio token, puede usar el siguiente script para cargar sus datos. Después de cargar los datos de su primera estación, vaya a aqicn.org/data-feed/verification/ para configurar sus estaciones y verificar los datos cargados.

Plataformas de software compatibles:

Proporcionamos el software listo para usar para esas 3 plataformas:

  • Arduino: si tiene una CPU Arduino, utilice el software listo para usar disponible en github.com en aqicn/gaia-a08-arduino.
  • Python: use el fragmento de código a continuación
  • Línea de comando (CURL): use el fragmento de código a continuación

Si no tiene ninguna estación de monitoreo y le gustaría obtener una, consulte nuestras estaciones de monitoreo de calidad del aire GAIA.

Si prefieres una estación de bricolaje, consulta la GAIA A08.


--

Código de muestra (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) 

Código de muestra (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}]\ 
}'

Código de muestra (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(); 
}

Opciones de API

Parameter Type Optional/Mandatory Explanations
token string mandatory

Obtenga su propio token de aqicn.org/data-platform/token.

station
station.id string mandatory

ID de estación única: puede seleccionar cualquier nombre con un máximo de 128 caracteres.
Este nombre sólo se utiliza internamente para usted. Nadie más verá esta identificación.

station.name string optional

Nombre de la estación: podría ser, por ejemplo, el nombre de su edificio, el nombre de una calle, el nombre de un departamento universitario o el código de su estación meteorológica personal.
Este nombre se utilizará como sufijo para la URL de su estación.

station.latitude float optional

Longitud de tu estación

station.longitude float optional

Longitud de tu estación

organization
org.website string optional

Si tiene un sitio web con más información sobre su estación/sensor, agregaremos este enlace en nuestro mapa cuando lo utilicemos para ver su estación.

org.name string optional

Si especifica un sitio web, este "nombre de la organización" se asociará al sitio web.

readings
readings[*].specie string mandatory

Nombre del contaminante que está reportando. Para sensores de gas, utilice: "pm2.5", "pm10", "pm1.0", ... Para sensores de gas, utilice: "co2", "no2", "o3", ... Para sensores meteorológicos, use: "temperatura", "humedad", "presión", "velocidad del viento", "ráfaga de viento", "dirección del viento", ..
En realidad, puede usar el nombre de cualquier especie que desee. Cuando su estación sea validada, los nombres quedarán normalizados en nuestro sistema.

readings[*].value float mandatory

Si su sensor produce valores cada segundo y solo los carga cada minuto, este valor debe ser el promedio de todos los valores leídos durante el último minuto.

readings[*].unit string optional

Unidad del valor. Por ejemplo, "mg/m3" para sensor de polvo, ppb para sensores de gas, C para sensor de temperatura.

readings[*].time string optional

Fecha y Hora de la lectura en formato ISO 8601

readings[*].min float optional

Si los valores de lectura se basan en el promedio de varios valores, entonces esto corresponde al valor mínimo de todos los valores utilizados para el promedio.

readings[*].max float optional

Si los valores de lectura se basan en el promedio de varios valores, entonces esto corresponde al valor máximo de todos los valores utilizados para el promedio.

readings[*].median float optional

Si los valores de lectura se basan en el promedio de varios valores, entonces esto corresponde al valor medio de todos los valores utilizados para el promedio.

readings[*].stddev float optional

Si los valores de lectura se basan en el promedio de varios valores, esto corresponde a la desviación estándar de todos los valores utilizados para el promedio.

readings[*].averaging float optional

Si los valores anteriores se basan en el promedio de varios valores, entonces esto corresponde a la duración, en segundos, del período de promedio.
Por ejemplo, utilice 60 para un promedio de datos por minuto y 3600 para un promedio por hora.

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

Ejemplo 2

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

Ejemplo de código completo

Puede usar este código para leer continuamente desde un sensor SDS y cargarlo cada minuto: (el script también está disponible en 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) 
 

¿Conoces alguna estación de calidad del aire en tu zona?
¿Por qué no participar en el mapa con tu propia estación de calidad del aire?

Nuestros monitores de calidad del aire GAIA son muy fáciles de configurar: Sólo necesitas un punto de acceso WIFI y una fuente de alimentación compatible con USB.

Una vez conectado, sus niveles de contaminación del aire en tiempo real están disponibles instantáneamente en los mapas y a través de la API.

La estación viene con un cable de alimentación impermeable de 10 metros, una fuente de alimentación USB, equipo de montaje y un panel solar opcional.

Acerca de la calidad del aire y la medición de la contaminación:

Acerca de los niveles de calidad del aire

ICACalidad del AireProteja su Salud
0 - 50 Buena No se anticipan impactos a la salud cuando la calidad del aire se encuentra en este intervalo.
51 -100 Moderada Las personas extraordinariamente sensitivas deben considerar limitación de los esfuerzos físicos excesivos y prolongados al aire libre.
101-150 Dañina a la Salud de los Grupos Sensitivos Los niños y adultos activos, y personas con enfermedades respiratorias tales como el asma, deben evitar los esfuerzos físicos excesivos y prolongados al aire libre.
151-200 Dañina a la Salud Los niños y adultos activos, y personas con enfermedades respiratorias tales como el asma, deben evitar los esfuerzos excesivos prolongados al aire libre; las demás personas, especialmente los niños, deben limitar los esfuerzos físicos excesivos y prolongados al aire libre.
201-300 Muy Dañina a la Salud Los niños y adultos activos, y personas con enfermedades respiratorias tales como el asma, deben evitar todos los esfuerzos excesivos al aire libre; las demás personas, especialmente los niños, deben limitar los esfuerzos físicos excesivos al aire libre.
300+ Arriesgado

Para saber más sobre la calidad del aire y la contaminación, comprobar la tema Calidad wikipedia Air o Guía airnow a la calidad del aire y su salud .

Para obtener consejos de salud muy útiles de Beijing doctor Richard Saint Cyr MD, compruebe www.myhealthbeijing.com blog.


Aviso de uso: Todos los datos de Calidad del aire no están validados en el momento de la publicación, y debido a la garantía de calidad, estos datos pueden modificarse, sin previo aviso, en cualquier momento. El proyecto World Air Quality Index ha ejercido todas las habilidades y cuidados razonables para compilar el contenido de esta información y en ningún caso el World Air Quality Index o el equipo del proyecto será responsable en el contrato, agravio o de otra manera por cualquier pérdida, lesión o daño que surja directa o indirectamente del suministro de esta información.



Configuración


Configuración de idioma:


Temperature unit:
Celcius