From 254dc0fb0dec731742b1b6b5c92be0cbb9898c0f Mon Sep 17 00:00:00 2001 From: Mike Skalnik Date: Thu, 2 Nov 2023 16:59:30 -0700 Subject: [PATCH 1/7] =?UTF-8?q?New=20API=20key=20=F0=9F=94=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app.js b/app.js index aa770d0..8c78195 100644 --- a/app.js +++ b/app.js @@ -3,6 +3,7 @@ let coord; let closestSensor; + const KEY="BA110377-679A-11EE-A8AF-42010A80000A" function onStart() { document.getElementById("powerwash").onclick = clearStorage; @@ -60,7 +61,7 @@ function fetchSensorListAndShowAQI() { const url = - "https://api.purpleair.com/v1/sensors?api_key=AA055D5D-E333-11EC-8561-42010A800005&fields=longitude,latitude&location_type=0&max_age=300"; + `https://api.purpleair.com/v1/sensors?api_key=${KEY}&fields=longitude,latitude&location_type=0&max_age=300`; window .fetch(url) @@ -79,7 +80,7 @@ function updateWithSensor(sensor) { announceState("Getting sensor data"); - const url = `https://api.purpleair.com/v1/sensors/${sensor.id}?api_key=AA055D5D-E333-11EC-8561-42010A800005&fields=pm2.5_10minute_a,pm2.5_10minute_b,humidity`; + const url = `https://api.purpleair.com/v1/sensors/${sensor.id}?api_key=${KEY}&fields=pm2.5_10minute_a,pm2.5_10minute_b,humidity`; window .fetch(url) From eab3218405c89a0922ea04fd2eeaa5b29029d20c Mon Sep 17 00:00:00 2001 From: Mike Skalnik Date: Thu, 2 Nov 2023 17:09:16 -0700 Subject: [PATCH 2/7] =?UTF-8?q?Pass=20the=20key=20in=20differently=20?= =?UTF-8?q?=F0=9F=9B=B3=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/app.js b/app.js index 8c78195..eb692a0 100644 --- a/app.js +++ b/app.js @@ -3,7 +3,11 @@ let coord; let closestSensor; - const KEY="BA110377-679A-11EE-A8AF-42010A80000A" + const FETCH_OPTIONS = { + headers: { + "X-API-Key": "BA110377-679A-11EE-A8AF-42010A80000A", + } + } function onStart() { document.getElementById("powerwash").onclick = clearStorage; @@ -61,10 +65,10 @@ function fetchSensorListAndShowAQI() { const url = - `https://api.purpleair.com/v1/sensors?api_key=${KEY}&fields=longitude,latitude&location_type=0&max_age=300`; + `https://api.purpleair.com/v1/sensors?fields=longitude,latitude&location_type=0&max_age=300`; window - .fetch(url) + .fetch(url, FETCH_OPTIONS) .then((response) => response.json()) .then((response) => { if (response.code && response.code >= 400 && response.message) { @@ -80,10 +84,10 @@ function updateWithSensor(sensor) { announceState("Getting sensor data"); - const url = `https://api.purpleair.com/v1/sensors/${sensor.id}?api_key=${KEY}&fields=pm2.5_10minute_a,pm2.5_10minute_b,humidity`; + const url = `https://api.purpleair.com/v1/sensors/${sensor.id}?fields=pm2.5_10minute_a,pm2.5_10minute_b,humidity`; window - .fetch(url) + .fetch(url, FETCH_OPTIONS) .then((response) => response.json()) .then(updateAQI) .catch(purpleError); From ad6edb694d8ef7c5205fa637b49e59d6aad2ed73 Mon Sep 17 00:00:00 2001 From: Mike Skalnik Date: Thu, 2 Nov 2023 17:31:37 -0700 Subject: [PATCH 3/7] =?UTF-8?q?This=20isn't=20referenced=20=F0=9F=94=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app.js b/app.js index eb692a0..af24db3 100644 --- a/app.js +++ b/app.js @@ -236,10 +236,6 @@ return `https://www.purpleair.com/map?opt=1/i/mAQI/a0/cC5&select=${closestSensor.id}#14/${coord.latitude}/${coord.longitude}`; } - function aqanduAQIFromPM(pm) { - return aqiFromPM(0.778 * pm + 2.65); - } - // From https://www.epa.gov/sites/default/files/2021-05/documents/toolsresourceswebinar_purpleairsmoke_210519b.pdf final slide function epaAQIFromPMandHumidity(pm, humidity) { if (pm < 50) { From f9897fec4f8a093b77a0ab1cc08bdd85904b05e9 Mon Sep 17 00:00:00 2001 From: Mike Skalnik Date: Thu, 14 Dec 2023 15:56:43 -0800 Subject: [PATCH 4/7] =?UTF-8?q?Add=20a=20bounding=20box=20=E2=9B=B9?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index af24db3..d5b97c5 100644 --- a/app.js +++ b/app.js @@ -64,8 +64,9 @@ } function fetchSensorListAndShowAQI() { + bounding_box = boundingBox(coord, 10) // 10km bounding box const url = - `https://api.purpleair.com/v1/sensors?fields=longitude,latitude&location_type=0&max_age=300`; + `https://api.purpleair.com/v1/sensors?fields=longitude,latitude&location_type=0&max_age=300&nwlng=${bounding_box.nw.longitude}&nwlat=${bounding_box.nw.latitude}&selng=${bounding_box.se.longitude}&selat=${bounding_box.se.latitude}`; window .fetch(url, FETCH_OPTIONS) @@ -232,6 +233,28 @@ return 12742 * Math.asin(Math.sqrt(a)); } + // Shoutout to ChatGPT + function boundingBox(coordinate, distance) { + const distanceInRadians = distance / 6371; // Earth's radius in kilometers + + // Calculate bounding box coordinates + const latMin = coordinate.latitude - (distanceInRadians * (180 / Math.PI)); + const latMax = coordinate.latitude + (distanceInRadians * (180 / Math.PI)); + const lonMin = coordinate.longitude - (distanceInRadians * (180 / Math.PI) / Math.cos(coordinate.latitude * (Math.PI / 180))); + const lonMax = coordinate.longitude + (distanceInRadians * (180 / Math.PI) / Math.cos(coordinate.latitude * (Math.PI / 180))); + + return { + nw: { + latitude: latMax, + longitude: lonMin + }, + se: { + latitude: latMin, + longitude: lonMax + } + }; + } + function getPurpleAirLink() { return `https://www.purpleair.com/map?opt=1/i/mAQI/a0/cC5&select=${closestSensor.id}#14/${coord.latitude}/${coord.longitude}`; } From 72f6c68e7ce0b03027cb9a2059d49364bbb97836 Mon Sep 17 00:00:00 2001 From: Mike Skalnik Date: Thu, 14 Dec 2023 16:10:51 -0800 Subject: [PATCH 5/7] =?UTF-8?q?Toss=20sensor=20cache=20if=20too=20far=20?= =?UTF-8?q?=F0=9F=91=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app.js b/app.js index d5b97c5..a25210a 100644 --- a/app.js +++ b/app.js @@ -39,6 +39,7 @@ try { const cachedSensors = window.localStorage.getItem("sensors"); sensor_data = JSON.parse(cachedSensors); + console.log(sensor_data) if (sensor_data == null) { throw "Sensor data not cached"; } @@ -49,6 +50,11 @@ throw "Sensor data is more than a day old"; } sensor = findClosestSensor(sensor_data.data); + + if (sensor.distance > 10) { + throw "Nearest sensor is over 10km away"; + } + updateWithSensor(sensor); } catch (exception) { console.log("Exception while reading cached sensor data"); From a60f27f79fddc7146d593a43c71ea61852b528b9 Mon Sep 17 00:00:00 2001 From: Mike Skalnik Date: Thu, 14 Dec 2023 16:12:55 -0800 Subject: [PATCH 6/7] =?UTF-8?q?No=20wonder=20it=20was=20never=20cached=20?= =?UTF-8?q?=F0=9F=A4=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app.js b/app.js index a25210a..99c8a50 100644 --- a/app.js +++ b/app.js @@ -39,11 +39,10 @@ try { const cachedSensors = window.localStorage.getItem("sensors"); sensor_data = JSON.parse(cachedSensors); - console.log(sensor_data) if (sensor_data == null) { throw "Sensor data not cached"; } - if (sensor_data.version !== 1) { + if (sensor_data.version !== 2) { throw "Sensor data is the wrong version"; } if (Date.now() > sensor_data.timestamp + 86400 * 1000) { From c204fe2750fff3b25bacc8855f59803a09adef7f Mon Sep 17 00:00:00 2001 From: Mike Skalnik Date: Thu, 14 Dec 2023 16:22:41 -0800 Subject: [PATCH 7/7] =?UTF-8?q?Up=20this=20to=205=20minutes=20=E2=9C=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.js b/app.js index 99c8a50..67a3784 100644 --- a/app.js +++ b/app.js @@ -138,7 +138,7 @@ }; } - setTimeout(() => getLocation(), 60000); + setTimeout(() => getLocation(), 300000); } function explainPermissionsRequest() {