| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- import {firebaseConfig} from './config';
- import {initializeApp} from 'firebase/app';
- import {getDatabase, onValue, orderByChild, query, ref, startAt} from 'firebase/database';
- import {Reading} from './types';
- import {createGauges, createGraphs} from './graphs';
- import {processData} from './processData';
- import {HOUR_OPTIONS, HOURS_DEFAULT, HOURS_QUERY, MAX_HOURS_AGO} from './consts';
- import {getWindowTime} from './utils';
- const app = initializeApp(firebaseConfig);
- const rtdb = getDatabase(app);
- document.body.onload = init;
- async function init() {
- const hoursAgo = getHoursAgo();
- const readings:Reading[] = await getRecentData(hoursAgo);
- showLatestReading(readings);
- // Force a 15-minute window for the gauges, to ensure it shows the most
- // up-to-date value it can (that's had spikes filtered out)
- const gaugeValues = processData(
- readings.slice(-10),
- { alignWindow: 10 }
- );
- createGauges(
- gaugeValues,
- document.getElementById('gauges')
- );
- // Have graphs use a potentially longer window time, so they don't show as
- // many elements when a longer time is selected.
- const graphValues = processData(readings, {
- alignWindow: getWindowTime(hoursAgo)
- });
- createGraphs(
- graphValues,
- document.getElementById('time-series-graphs')
- );
- showHourSelection();
- }
- function getHoursAgo():number {
- const query = new URLSearchParams(document.location.search)
- .get(HOURS_QUERY);
- if(!query) {
- return HOURS_DEFAULT;
- }
- let hours = parseInt(query);
- if(isNaN(hours) || hours > MAX_HOURS_AGO) {
- return HOURS_DEFAULT;
- }
- return hours;
- }
- function showLatestReading(readings:Reading[]) {
- const span = document.getElementById('last-update-value');
- span.textContent = new Date(readings.pop().time).toLocaleTimeString();
- }
- function showHourSelection() {
- const options:HTMLSelectElement =
- document.getElementById('hours-ago') as HTMLSelectElement;
- const current = getHoursAgo();
- for(let h of HOUR_OPTIONS) {
- const opt = document.createElement('option');
- opt.value = h.toString();
- opt.textContent = `Last ${h} hours`;
- if(h === current) {
- opt.selected = true;
- }
- options.add(opt);
- }
- options.addEventListener('change', () => {
- const selection = options.value;
- const newUrl = `${document.location.href.split('?')[0]}?hours=${selection}`;
- document.location.href = newUrl;
- });
- }
- async function getRecentData(
- hoursAgo:number = 2
- ): Promise<Reading[]> {
- const since = new Date().getTime() - (hoursAgo * 3600 * 1000);
- const outdoors = ref(rtdb, 'outdoor');
- const search = query(
- outdoors,
- orderByChild('time'),
- startAt(since)
- );
- return new Promise<Reading[]>((res, err) => {
- let values:Reading[] = [];
- onValue(search, snapshot => {
- snapshot.forEach(child => {
- values.push(child.val());
- });
- res(values);
- }, {
- onlyOnce: true
- });
- });
- }
|