API za prijenos podataka i uzorci skripti

Prvi korak je dobivanje tokena sa stranice podatkovne platforme .

Nakon što dobijete vlastiti token, možete koristiti sljedeću skriptu za prijenos podataka. Nakon što učitate svoje prve podatke o stanici, idite na aqicn.org/data-feed/verification/ da konfigurirate svoje stanice i provjerite učitane podatke.

Podržane softverske platforme:

Nudimo softver spreman za korištenje za te 3 platforme:

  • Arduino : Ako imate Arduino CPU, koristite softver spreman za korištenje dostupan na github.com na aqicn/gaia-a08-arduino .
  • Python: upotrijebite isječak koda u nastavku
  • Naredbeni redak (CURL): Upotrijebite isječak koda u nastavku

Ako nemate stanicu za praćenje, a željeli biste je nabaviti, provjerite naše GAIA stanice za praćenje kvalitete zraka.

Ako više volite DIY stanicu, provjerite GAIA A08 .


--

Primjer koda (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) 

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

Primjer koda (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 opcije

Parameter Type Optional/Mandatory Explanations
token string mandatory

Nabavite vlastiti token s aqicn.org/data-platform/token .

station
station.id string mandatory

Jedinstveni ID postaje - možete odabrati bilo koje ime s najviše 128 znakova.
Ovo se ime koristi samo interno za vas. Nitko drugi neće vidjeti ovaj ID

station.name string optional

Naziv postaje - može biti na primjer naziv vaše zgrade, naziv ulice, naziv sveučilišnog odjela, šifra vaše osobne meteorološke stanice.
Ovo će se ime koristiti kao sufiks za URL vaše postaje.

station.latitude float optional

Zemljopisna dužina vaše postaje

station.longitude float optional

Zemljopisna dužina vaše postaje

organization
org.website string optional

Ako imate web stranicu s više informacija o vašoj stanici/senzoru, dodat ćemo ovu vezu na našu kartu kada se koristi pogledajte svoju stanicu

org.name string optional

Ako navedete web mjesto, ovaj "naziv organizacije" bit će povezan s web mjestom.

readings
readings[*].specie string mandatory

Naziv zagađivača koji prijavljujete. Za senzore plina koristite: "pm2.5", "pm10", "pm1.0", ... Za senzor plina koristite: "co2", "no2", "o3", ... Za senzor vremena, koristiti: "temp", "vlažnost", "tlak", "brzina vjetra", "udar vjetra", "smjer vjetra", ..
Zapravo možete koristiti bilo koje ime vrste koje želite. Kada vaša stanica bude potvrđena, imena će se normalizirati u našem sustavu.

readings[*].value float mandatory

Ako vaš senzor proizvodi vrijednosti svake sekunde, a vi učitavate samo svake minute, ova bi vrijednost trebala biti prosjek svih vrijednosti očitanih tijekom protekle minute.

readings[*].unit string optional

Jedinica vrijednosti. Npr. "mg/m3" za senzor prašine, ppb za senzore plina, C za senzor temperature..

readings[*].time string optional

Datum i vrijeme očitanja u formatu ISO 8601

readings[*].min float optional

Ako se očitane vrijednosti temelje na prosjeku nekoliko vrijednosti, tada to odgovara minimalnoj vrijednosti svih vrijednosti korištenih za prosjek.

readings[*].max float optional

Ako se očitane vrijednosti temelje na prosjeku nekoliko vrijednosti, tada to odgovara maksimalnoj vrijednosti svih vrijednosti korištenih za prosjek.

readings[*].median float optional

Ako se očitane vrijednosti temelje na prosjeku nekoliko vrijednosti, tada to odgovara srednjoj vrijednosti svih vrijednosti korištenih za prosjek.

readings[*].stddev float optional

Ako se očitane vrijednosti temelje na prosjeku nekoliko vrijednosti, tada to odgovara standardnoj devijaciji svih vrijednosti korištenih za prosjek.

readings[*].averaging float optional

Ako se gornje vrijednosti temelje na usrednjavanju nekoliko vrijednosti, tada to odgovara trajanju razdoblja usrednjavanja u sekundama.
Na primjer, upotrijebite 60 za prosječne podatke po minuti i 3600 za prosjek po satu.

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

Primjer 2

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

Kompletan primjer koda

Možete koristiti ovaj kod za kontinuirano očitavanje sa SDS senzora i učitavanje svake minute: (skripta također dostupna na 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) 
 

Znate li za neke stanice za kvalitetu zraka u vašem području?
zašto ne biste sudjelovali na karti sa svojom vlastitom stanicom za kvalitetu zraka?

Naše GAIA monitore kvalitete zraka vrlo je jednostavno postaviti: potrebna vam je samo WIFI pristupna točka i USB kompatibilno napajanje.

Nakon povezivanja, vaše razine onečišćenja zraka u stvarnom vremenu trenutno su dostupne na kartama i putem API-ja.

Stanica dolazi s 10-metarskim vodootpornim kabelom za napajanje, USB napajanjem, opremom za montažu i dodatnim solarnim panelom.

O kvaliteti zraka i mjerenju onečišćenja:

O razinama kvalitete zraka

- Vrijednosti indeksa kvalitete zraka (AQI).Razine zdravstvene zabrinutosti
0 - 50 Dobro Kvaliteta zraka smatra se zadovoljavajućom, a onečišćenje zraka predstavlja mali ili nikakav rizik
51 -100 umjeren Kvaliteta zraka je prihvatljiva; ali ipak, neki zagađivači mogu prouzrokovati umjerenu zabrinutost za zdravlje vrlo malog broja ljudi koji su neobično osjetljivi na onečišćenje zraka.
101-150 Nezdravo za osjetljive skupine Članovi osjetljivih skupina mogu imati posljedice na zdravlje. Vjerovatno neće imati utjecaja na širu popilaciju.
151-200 nezdrav Svatko može početi osjećati zdravstvene posljedice; članovi osjetljivih skupina mogu imati ozbiljnije zdravstvene posljedice
201-300 Vrlo nezdravo Zdravstvena upozorenja o izvanrednim okolnostima. Veća je vjerojatnost da će cijela populacija biti pogođena.
300+ Opasan Upozorenje o zdravlju: svatko može imati ozbiljnije zdravstvene posljedice

Kako biste saznali više o kvaliteti zraka i onečišćenju, pogledajte temu o kvaliteti zraka na wikipediji ili airnow vodič o kvaliteti zraka i vašem zdravlju .

Za vrlo korisne zdravstvene savjete pekinškog doktora Richarda Saint Cyra, MD, pogledajte blog www.myhealthbeijing.com .


Obavijest o korištenju: Svi podaci o kvaliteti zraka nisu dozvoljeni u trenutku objavljivanja, a zbog osiguranja kvalitete ti se podaci mogu u bilo kojem trenutku mijenjati bez prethodne najave. Projekt Indeks svjetske kakvoće zraka iskoristio je svu razumnu vještinu i pažnju pri sastavljanju sadržaja tih informacija i ni pod kojim okolnostima neće Svjetski indeks kvaliteta zraka projektni tim ili njegovi agenti odgovorni su za ugovor, prekršaj ili drugačije za bilo kakav gubitak, ozljedu ili štetu koja proizlazi izravno ili neizravno iz opskrbe tim podacima.



Settings


Language Settings:


Temperature unit:
Celcius