Data Upload API & Samples scripts

ຂັ້ນຕອນທໍາອິດແມ່ນເພື່ອເອົາ token ຈາກ ຫນ້າ data-platform .

ເມື່ອທ່ານມີ token ຂອງທ່ານເອງ, ທ່ານສາມາດນໍາໃຊ້ສະຄິບຕໍ່ໄປນີ້ເພື່ອອັບໂຫລດຂໍ້ມູນຂອງທ່ານ. ຫຼັງ​ຈາກ​ທີ່​ທ່ານ​ອັບ​ໂຫຼດ​ຂໍ້​ມູນ​ສະ​ຖາ​ນີ​ທໍາ​ອິດ​ຂອງ​ທ່ານ​, ໄປ​ທີ່ aqicn.org/data-feed/verification/ ເພື່ອ​ກໍາ​ນົດ​ຄ່າ​ສະ​ຖາ​ນີ​ຂອງ​ທ່ານ​ແລະ​ກວດ​ສອບ​ຂໍ້​ມູນ​ທີ່​ອັບ​ໂຫຼດ​ໄດ້​.

ເວທີຊອບແວທີ່ຮອງຮັບ:

ພວກ​ເຮົາ​ສະ​ຫນອງ​ຄວາມ​ພ້ອມ​ທີ່​ຈະ​ນໍາ​ໃຊ້​ຊອບ​ແວ​ສໍາ​ລັບ 3 ເວ​ທີ​ທີ່​:

  • Arduino : ຖ້າທ່ານມີ CPU Arduino, ໃຫ້ໃຊ້ຊອຟແວທີ່ພ້ອມໃຊ້ແລ້ວໃນ github.com ທີ່ aqicn/gaia-a08-arduino .
  • Python: ໃຊ້ code-snippet ຂ້າງລຸ່ມນີ້
  • ເສັ້ນຄໍາສັ່ງ (CURL): ໃຊ້ລະຫັດ-snippet ຂ້າງລຸ່ມນີ້

ຖ້າ​ຫາກ​ວ່າ​ທ່ານ​ບໍ່​ມີ​ສະ​ຖາ​ນີ​ຕິດ​ຕາມ​ກວດ​ກາ​ໃດ​ຫນຶ່ງ​, ແລະ​ຢາກ​ຈະ​ໄດ້​ຮັບ​ຫນຶ່ງ​, ໃຫ້​ກວດ​ເບິ່ງ​ສະ​ຖາ​ນີ​ຕິດ​ຕາມ​ຄຸນ​ນະ​ພາບ​ອາ​ກາດ GAIA ຂອງ​ພວກ​ເຮົາ​.

ຖ້າທ່ານຕ້ອງການສະຖານີ DIY, ໃຫ້ກວດເບິ່ງ GAIA A08 .


--

ລະຫັດຕົວຢ່າງ (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) 

ລະຫັດຕົວຢ່າງ (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}]\ 
}'

ລະຫັດຕົວຢ່າງ (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

Parameter Type Optional/Mandatory Explanations
token string mandatory

ຮັບໂທເຄັນຂອງທ່ານເອງຈາກ aqicn.org/data-platform/token .

station
station.id string mandatory

ID ສະຖານີທີ່ເປັນເອກະລັກ - ທ່ານສາມາດເລືອກຊື່ໃດກໍໄດ້ທີ່ມີຕົວອັກສອນສູງສຸດ 128 ຕົວ.
ຊື່ນີ້ຖືກໃຊ້ພາຍໃນສຳລັບເຈົ້າເທົ່ານັ້ນ. ຈະບໍ່ມີໃຜເຫັນບັດປະຈຳຕົວນີ້

station.name string optional

ຊື່​ຂອງ​ສະ​ຖາ​ນີ - ອາດ​ຈະ​ເປັນ​ຕົວ​ຢ່າງ​ຊື່​ຂອງ​ອາ​ຄານ​ຂອງ​ທ່ານ​, ຊື່​ຂອງ​ຖະ​ຫນົນ​, ຊື່​ຂອງ​ພະ​ແນກ​ວິ​ທະ​ຍາ​ໄລ​, ລະ​ຫັດ​ຂອງ​ສະ​ຖາ​ນີ​ດິນ​ຟ້າ​ອາ​ກາດ​ສ່ວນ​ບຸກ​ຄົນ​ຂອງ​ທ່ານ​.
ຊື່ນີ້ຈະຖືກໃຊ້ເປັນຄຳຕໍ່ທ້າຍສຳລັບ URL ສະຖານີຂອງທ່ານ.

station.latitude float optional

Longitude ຂອງສະຖານີຂອງທ່ານ

station.longitude float optional

Longitude ຂອງສະຖານີຂອງທ່ານ

organization
org.website string optional

ຖ້າທ່ານມີເວັບໄຊທ໌ທີ່ມີຂໍ້ມູນເພີ່ມເຕີມກ່ຽວກັບສະຖານີ / ເຊັນເຊີຂອງທ່ານ, ພວກເຮົາຈະເພີ່ມການເຊື່ອມຕໍ່ນີ້ໃນແຜນທີ່ຂອງພວກເຮົາເມື່ອໃຊ້ເບິ່ງສະຖານີຂອງທ່ານ.

org.name string optional

ຖ້າທ່ານລະບຸເວັບໄຊທ໌, "ຊື່ອົງການຈັດຕັ້ງ" ນີ້ຈະຖືກເຊື່ອມໂຍງກັບເວັບໄຊທ໌.

readings
readings[*].specie string mandatory

ຊື່ຂອງມົນລະພິດທີ່ທ່ານກໍາລັງລາຍງານ. ສໍາລັບເຊັນເຊີແກັສ, ໃຊ້: "pm2.5", "pm10", "pm1.0", ... ສໍາລັບເຊັນເຊີ gaz, ໃຊ້: "co2", "no2", "o3", ... ສໍາລັບເຊັນເຊີສະພາບອາກາດ, ໃຊ້: "ອຸນຫະພູມ", "ຄວາມຊຸ່ມ", "ຄວາມກົດດັນ", "ຄວາມໄວລົມ", "ລົມພັດ", "ທິດທາງລົມ", ..
ຕົວຈິງແລ້ວທ່ານສາມາດນໍາໃຊ້ຊື່ຊະນິດໃດນຶ່ງທີ່ທ່ານຕ້ອງການ. ໃນເວລາທີ່ທ່ານສະຖານີຖືກກວດສອບ, ຊື່ຈະຖືກປັບປຸງເປັນປົກກະຕິໃນລະບົບຂອງພວກເຮົາ.

readings[*].value float mandatory

ຖ້າເຊັນເຊີຂອງທ່ານຜະລິດຄ່າທຸກໆວິນາທີ, ແລະທ່ານພຽງແຕ່ອັບໂຫລດທຸກໆນາທີ, ຄ່ານີ້ຄວນຈະເປັນຄ່າສະເລ່ຍຂອງຄ່າທັງຫມົດທີ່ອ່ານໃນນາທີທີ່ຜ່ານມາ.

readings[*].unit string optional

ຫົວໜ່ວຍຂອງມູນຄ່າ. ຕົວຢ່າງ "mg/m3" ສໍາລັບເຊັນເຊີຂີ້ຝຸ່ນ, ppb ສໍາລັບເຊັນເຊີອາຍແກັສ, C ສໍາລັບເຊັນເຊີອຸນຫະພູມ..

readings[*].time string optional

ວັນທີ ແລະເວລາຂອງການອ່ານໃນຮູບແບບ ISO 8601

readings[*].min float optional

ຖ້າຄ່າການອ່ານແມ່ນອີງໃສ່ຄ່າສະເລ່ຍຂອງຫຼາຍຄ່າ, ມັນເທົ່າກັບຄ່າ min ຂອງຄ່າທັງຫມົດທີ່ໃຊ້ສໍາລັບການສະເລ່ຍ.

readings[*].max float optional

ຖ້າຄ່າການອ່ານແມ່ນອີງໃສ່ຄ່າສະເລ່ຍຂອງຫຼາຍຄ່າ, ມັນເທົ່າກັບຄ່າສູງສຸດຂອງຄ່າທັງໝົດທີ່ໃຊ້ສໍາລັບການສະເລ່ຍ.

readings[*].median float optional

ຖ້າຄ່າການອ່ານແມ່ນອີງໃສ່ຄ່າສະເລ່ຍຂອງຫຼາຍຄ່າ, ນີ້ເທົ່າກັບຄ່າສະເລ່ຍຂອງຄ່າທັງຫມົດທີ່ໃຊ້ສໍາລັບການສະເລ່ຍ.

readings[*].stddev float optional

ຖ້າຄ່າການອ່ານແມ່ນອີງໃສ່ຄ່າສະເລ່ຍຂອງຫຼາຍຄ່າ, ນີ້ເທົ່າກັບມາດຕະຖານ deviation ຂອງຄ່າທັງຫມົດທີ່ໃຊ້ສໍາລັບການສະເລ່ຍ.

readings[*].averaging float optional

ຖ້າຄ່າຂ້າງເທິງແມ່ນອີງໃສ່ຄ່າສະເລ່ຍຂອງຫຼາຍຄ່າ, ຫຼັງຈາກນັ້ນ, ນີ້ເທົ່າກັບໄລຍະເວລາ, ເປັນວິນາທີ, ຂອງໄລຍະເວລາສະເລ່ຍ.
ຕົວຢ່າງ, ໃຊ້ 60 ສໍາລັບຂໍ້ມູນສະເລ່ຍຕໍ່ນາທີ ແລະ 3600 ສໍາລັບຄ່າສະເລ່ຍຕໍ່ຊົ່ວໂມງ.

ຕົວຢ່າງ 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-05T10:54:13+09:00","specie":"pm2.5", "value": 393.3, "unit":"mg/m3", "min":390.3, "max": 402.3, "stddev": 0.332},  
		{"time":"2024-12-05T10:54:13+09:00","specie":"pm10", "value": 109.3, "unit":"mg/m3"}, 
		{"time":"2024-12-05T10:54:13+09:00","specie":"co2", "value": 459.3, "unit":"ppb"}, 
		{"time":"2024-12-05T10:54:13+09:00","specie":"temp", "value": 26.8, "unit":"C"}, 
	] 
}

ຕົວຢ່າງ 2

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

ຕົວຢ່າງລະຫັດຄົບຖ້ວນ

ທ່ານ​ສາ​ມາດ​ນໍາ​ໃຊ້​ລະ​ຫັດ​ນີ້​ສໍາ​ລັບ​ການ​ອ່ານ​ຕໍ່​ເນື່ອງ​ຈາກ​ເຊັນ​ເຊີ SDS​, ແລະ​ການ​ອັບ​ໂຫຼດ​ທຸກ​ນາ​ທີ​: (ສະ​ຄິບ​ຍັງ​ມີ​ຢູ່​ໃນ 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) 
 

ເຈົ້າຮູ້ຈັກສະຖານີຄຸນນະພາບອາກາດຢູ່ໃນພື້ນທີ່ຂອງເຈົ້າບໍ?
ເປັນຫຍັງບໍ່ເຂົ້າຮ່ວມແຜນທີ່ກັບສະຖານີຄຸນນະພາບອາກາດຂອງທ່ານເອງ?

ເຄື່ອງຕິດຕາມຄຸນນະພາບອາກາດ GAIA ຂອງພວກເຮົາແມ່ນຕັ້ງງ່າຍຫຼາຍ: ທ່ານພຽງແຕ່ຕ້ອງການຈຸດເຂົ້າເຖິງ WIFI ແລະແຫຼ່ງສະໜອງພະລັງງານທີ່ເຂົ້າກັນໄດ້ກັບ USB.

ເມື່ອເຊື່ອມຕໍ່ແລ້ວ, ລະດັບມົນລະພິດທາງອາກາດໃນເວລາຈິງຂອງເຈົ້າແມ່ນມີຢູ່ໃນແຜນທີ່ ແລະຜ່ານ API ທັນທີ.

ສະຖານີດັ່ງກ່າວມາພ້ອມກັບສາຍໄຟທີ່ສາມາດກັນນ້ໍາໄດ້ 10 ແມັດ, ແຫຼ່ງສະຫນອງພະລັງງານ USB, ອຸປະກອນຕິດຕັ້ງແລະແຜງແສງອາທິດທາງເລືອກ.

ກ່ຽວກັບການວັດແທກຄຸນນະພາບອາກາດ ແລະມົນລະພິດ:

ກ່ຽວກັບລະດັບຄຸນນະພາບອາກາດ

- ດັດຊະນີຄຸນນະພາບອາກາດ (AQI) ຄ່າLevels of Health Concern
0 - 50 ດີ ຄຸນນະພາບທາງອາກາດຖືກພິຈາລະນາເປັນທີ່ພໍໃຈ, ແລະມົນລະພິດທາງອາກາດກໍ່ມີຄວາມສ່ຽງຫນ້ອຍຫຼືບໍ່ມີຄວາມສ່ຽງ
51 -100 ປານກາງ ຄຸນນະພາບທາງອາກາດແມ່ນການຮັບຮອງ; ຢ່າງໃດກໍ່ຕາມ, ສໍາລັບບາງມົນລະພິດອາດມີຄວາມກັງວົນກ່ຽວກັບສຸຂະພາບໃນລະດັບປານກາງສໍາລັບຈໍານວນຜູ້ທີ່ມີຄວາມເຄັ່ງຕຶງທີ່ຜິດປົກກະຕິກັບການມົນລະພິດທາງອາກາດ.
101-150 Unhealthy
for sensitive groups
ສະມາຊິກຂອງກຸ່ມທີ່ມີຄວາມອ່ອນໄຫວອາດຈະມີຜົນກະທົບຕໍ່ສຸຂະພາບ ປະຊາຊົນທົ່ວໄປບໍ່ໄດ້ຮັບຜົນກະທົບ.
151-200 ບໍ່ມີສຸຂະພາບດີ ທຸກໆຄົນອາດຈະເລີ່ມປະສົບຜົນກະທົບດ້ານສຸຂະພາບ; ສະມາຊິກຂອງກຸ່ມທີ່ມີຄວາມອ່ອນໄຫວອາດຈະມີຜົນກະທົບດ້ານສຸຂະພາບທີ່ຮ້າຍແຮງຫຼາຍ
201-300 Very
Unhealthy
ການເຕືອນໄພດ້ານສຸຂະພາບຂອງສະພາບສຸກເສີນ. ປະຊາກອນທັງຫມົດແມ່ນມັກຈະໄດ້ຮັບຜົນກະທົບ.
300+ ອັນຕະລາຍ ເຕືອນດ້ານສຸຂະພາບ: ທຸກໆຄົນອາດຈະມີຜົນກະທົບທາງສຸຂະພາບທີ່ຮ້າຍແຮງກວ່າເກົ່າ

ເພື່ອຮູ້ເພີ່ມເຕີມກ່ຽວກັບຄຸນນະພາບອາກາດ ແລະມົນລະພິດ, ໃຫ້ກວດເບິ່ງ ຫົວຂໍ້ຄຸນນະພາບອາກາດຂອງ wikipedia ຫຼື ຄູ່ມື airnow ກ່ຽວກັບຄຸນນະພາບອາກາດ ແລະສຸຂະພາບຂອງເຈົ້າ .

ສໍາລັບຄໍາແນະນໍາດ້ານສຸຂະພາບທີ່ເປັນປະໂຫຍດຫຼາຍຂອງທ່ານຫມໍປັກກິ່ງ Richard Saint Cyr MD, ກວດເບິ່ງ blog www.myhealthbeijing.com .


ແຈ້ງການນໍາໃຊ້: ຂໍ້ມູນຄຸນນະພາບອາກາດທັງຫມົດແມ່ນບໍ່ຖືກຕ້ອງໃນເວລາທີ່ພິມເຜີຍແຜ່, ແລະເນື່ອງຈາກການຮັບປະກັນຄຸນນະພາບຂອງຂໍ້ມູນເຫຼົ່ານີ້ອາດຈະຖືກປັບປຸງ, ໂດຍບໍ່ມີຂໍ້ສັງເກດ, ໃນທຸກເວລາ. ໂຄງການດັດຊະນີທາງອາກາດໂລກໄດ້ໃຊ້ທັກສະແລະການດູແລທີ່ສົມເຫດສົມຜົນທັງຫມົດໃນການລວບລວມເນື້ອໃນຂອງຂໍ້ມູນນີ້ແລະພາຍໃຕ້ສະພາບການໃດກໍ່ຕາມທີມງານຂອງໂຄງການໂລກຂອງອາກາດທາງໂລກຫຼືຕົວແທນຂອງມັນຈະຮັບຜິດຊອບໃນສັນຍາ, ຄວາມເສຍຫາຍຫຼືຄວາມເສຍຫາຍໃດໆ, ເກີດຂື້ນໂດຍກົງຫຼືໂດຍທາງອ້ອມຈາກການສະຫນອງຂໍ້ມູນນີ້.



Settings


Language Settings:


Temperature unit:
Celcius