API de upload de dados e scripts de amostras

A primeira etapa é obter um token da página da plataforma de dados.

Depois de ter seu próprio token, você pode usar o script a seguir para fazer upload de seus dados. Depois de fazer upload dos dados da primeira estação, acesse aqicn.org/data-feed/verification/ para configurar suas estações e verificar os dados enviados.

Plataformas de software suportadas:

Fornecemos software pronto para uso para essas 3 plataformas:

  • Arduino: se você tiver uma CPU Arduino, use o software pronto para uso disponível em github.com em aqicn/gaia-a08-arduino.
  • Python: Use o trecho de código abaixo
  • Linha de comando (CURL): Use o trecho de código abaixo

Se você não possui nenhuma estação de monitoramento e gostaria de adquirir uma, consulte nossas GAIA estações de monitoramento da qualidade do ar.

Se preferir uma estação DIY, confira GAIA A08.


--

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

Opções de API

Parameter Type Optional/Mandatory Explanations
token string mandatory

Obtenha seu próprio token em aqicn.org/data-platform/token.

station
station.id string mandatory

ID exclusivo da estação - você pode selecionar qualquer nome com no máximo 128 caracteres.
Este nome é usado apenas internamente para você. Ninguém mais verá este ID

station.name string optional

Nome da estação - pode ser, por exemplo, o nome do seu edifício, o nome de uma rua, o nome de um departamento universitário, o código da sua estação meteorológica pessoal.
Este nome será usado como sufixo para o URL da sua estação.

station.latitude float optional

Longitude da sua estação

station.longitude float optional

Longitude da sua estação

organization
org.website string optional

Se você tiver um site com mais informações sobre sua estação/sensor, adicionaremos este link em nosso mapa quando usarmos veja sua estação

org.name string optional

Se você especificar um site, esse “nome da organização” será associado ao site.

readings
readings[*].specie string mandatory

Nome do poluente que você está relatando. Para sensores de gás, use: "pm2.5", "pm10", "pm1.0", ... Para sensor de gás, use: "co2", "no2", "o3", ... Para sensor meteorológico, use: "temp", "umidade", "pressão", "velocidade do vento", "rajada de vento", "direção do vento", ..
Você pode usar qualquer nome de espécie que desejar. Quando sua estação for validada, os nomes serão normalizados em nosso sistema.

readings[*].value float mandatory

Se o seu sensor estiver produzindo valores a cada segundo e você fizer upload apenas a cada minuto, esse valor deverá ser a média de todos os valores lidos durante o último minuto.

readings[*].unit string optional

Unidade do valor. Por exemplo, "mg/m3" para sensor de poeira, ppb para sensores de gás, C para sensor de temperatura.

readings[*].time string optional

Data e hora da leitura no formato ISO 8601

readings[*].min float optional

Se os valores de leitura forem baseados na média de vários valores, então isso corresponderá ao valor mínimo de todos os valores usados ​​para a média.

readings[*].max float optional

Se os valores de leitura forem baseados na média de vários valores, então isso corresponderá ao valor máximo de todos os valores usados ​​para a média.

readings[*].median float optional

Se os valores de leitura forem baseados na média de vários valores, então isso corresponderá ao valor mediano de todos os valores usados ​​para a média.

readings[*].stddev float optional

Se os valores de leitura forem baseados na média de vários valores, isso corresponderá ao desvio padrão de todos os valores utilizados para a média.

readings[*].averaging float optional

Se os valores acima forem baseados na média de vários valores, então isso corresponderá à duração, em segundos, do período médio.
Por exemplo, use 60 para dados médios por minuto e 3600 para média horária.

Exemplo 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":"2025-03-07T13:28:31+09:00","specie":"pm2.5", "value": 393.3, "unit":"mg/m3", "min":390.3, "max": 402.3, "stddev": 0.332},
{"time":"2025-03-07T13:28:31+09:00","specie":"pm10", "value": 109.3, "unit":"mg/m3"},
{"time":"2025-03-07T13:28:31+09:00","specie":"co2", "value": 459.3, "unit":"ppb"},
{"time":"2025-03-07T13:28:31+09:00","specie":"temp", "value": 26.8, "unit":"C"},
]
}

Exemplo 2

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

Exemplo de código completo

Você pode usar este código para leitura contínua de um sensor SDS e upload a cada minuto: (script também disponível em 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)

Você conhece alguma estação de medição de qualidade do ar na sua área?
por que não participar do mapa com sua própria estação de qualidade do ar?

Nossos monitores de qualidade do ar GAIA são muito fáceis de configurar: você só precisa de um ponto de acesso WIFI e uma fonte de alimentação compatível com USB.

Uma vez conectado, seus níveis de poluição do ar em tempo real ficam instantaneamente disponíveis nos mapas e por meio da API.

A estação vem com um cabo de alimentação à prova d’água de 10 metros, uma fonte de alimentação USB, equipamento de montagem e um painel solar opcional.

Sobre a medição da aualidade do ar e poluição

Sobre os níveis de qualidade do ar

- Valores do Índice de Qualidade do Ar (AQI)Níveis de preocupação de saúde
0 - 50 Boa 0-50: Boa - A qualidade do ar é considerada satisfatória, a poluição do ar representa pouco ou nenhum risco
51 -100 Moderado 50-100: Moderado - A qualidade do ar é aceitável; No entanto, para alguns poluentes pode haver um problema de saúde moderada para um número muito pequeno de pessoas que são mais sensíveis à poluição do ar.
101-150 Não Saudável para Grupos Sensíveis Membros de grupos sensíveis podem ter efeitos na a saúde. O público em geral não é susceptível de ser afetado.
151-200 Não saudável 150-200: Insalubre - Toda a população pode começar a sentir os efeitos na saúde; membros de grupos sensíveis podem apresentar efeitos mais sérios de saúde.
201-300 Muito Prejudical à Saúde 200-300: Muito Insalubre - As advertências de saúde de situações de emergência. Toda a população é mais susceptível de ser afectada.
300+ Perigoso 300+: Perigoso - alerta de saúde: todos podem experimentar efeitos mais graves para a saúde

Para saber mais sobre Qualidade do Ar e Poluição, verifique o wikipedia Qualidade do Ar tópico ou o guia AIRNow a Qualidade do Ar e sua saúde.

Para informações sobre saúde muito úteis em Pequim, procure Doutor Richard Saint Cyr MD, consulte www.myhealthbeijing.com blogue.


Aviso de uso: Todos os dados da Qualidade do Ar não são validados no momento da publicação e, devido à garantia de qualidade, esses dados podem ser alterados, sem aviso prévio, a qualquer momento. O projeto Índice de Qualidade do Ar Mundial exerceu todas as habilidades e cuidados razoáveis na compilação do conteúdo desta informação e sob nenhuma circunstância o A equipe do projeto World Air Quality Index ou seus agentes podem ser responsabilizados em contrato, responsabilidade civil ou de outra forma por qualquer perda, lesão ou dano decorrente direta ou indiretamente do fornecimento desses dados.



Configurações


Configurações de Idioma:


Temperature unit:
Celcius