Update to push to firestore

This commit is contained in:
William Moore 2023-10-26 00:58:33 -05:00
parent c217a807a7
commit a865e2a89a
5 changed files with 3722 additions and 3349 deletions

1
.gitignore vendored
View File

@ -7,6 +7,7 @@ yarn-debug.log*
yarn-error.log* yarn-error.log*
lerna-debug.log* lerna-debug.log*
.pnpm-debug.log* .pnpm-debug.log*
google-services.json
# Diagnostic reports (https://nodejs.org/api/report.html) # Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

7077
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -5,8 +5,8 @@
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",
"scripts": { "scripts": {
"start": "npx tsc && node --experimental-specifier-resolution=node build/index.js", "start": "npx tsc && node build/index.js",
"start:dev": "export PORT=4500 npx tsc && node --experimental-specifier-resolution=node --trace-warnings build/index.js", "start:dev": "export PORT=4500 npx tsc && node build/index.js",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"repository": { "repository": {
@ -16,21 +16,11 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"async-lock": "^1.4.0",
"blinkdb": "^0.9.0",
"body-parser": "^1.20.1",
"cors": "^2.8.5",
"date-fns": "^2.29.3",
"dotenv": "^16.0.3", "dotenv": "^16.0.3",
"express": "^4.18.2", "firebase-admin": "^11.11.0",
"mongoose": "^6.8.4",
"node-fetch": "^3.3.0" "node-fetch": "^3.3.0"
}, },
"devDependencies": { "devDependencies": {
"@types/body-parser": "^1.19.2",
"@types/cors": "^2.8.13",
"@types/date-fns": "^2.6.0",
"@types/express": "^4.17.15",
"@types/node": "^18.11.18", "@types/node": "^18.11.18",
"typescript": "^4.9.4" "typescript": "^4.9.4"
} }

View File

@ -1,70 +1,49 @@
import bodyParser from 'body-parser';
import express from 'express';
import 'dotenv/config'; import 'dotenv/config';
import fetch from 'node-fetch'; import fetch from 'node-fetch';
import { subHours, subSeconds } from 'date-fns'
import {
createDB,
createTable,
insert,
many,
removeWhere,
uuid,
} from 'blinkdb';
const { json } = bodyParser; import admin, { ServiceAccount } from 'firebase-admin';
import { FieldValue } from 'firebase-admin/firestore';
import serviceAccount from './google-services.json' assert { type: "json" };
const RAIN_GAUGE_ENDPOINT = process.env.RAIN_GAUGE_ENDPOINT; const RAIN_GAUGE_ENDPOINT = process.env.RAIN_GAUGE_ENDPOINT;
const SOIL_SENSOR_ENDPOINT = process.env.SOIL_SENSOR_ENDPOINT; const SOIL_SENSOR_ENDPOINT = process.env.SOIL_SENSOR_ENDPOINT;
const TEASENSE_ENDPOINT = process.env.TEASENSE_ENDPOINT; const TEASENSE_ENDPOINT = process.env.TEASENSE_ENDPOINT;
const PORT = process.env.PORT || 3000;
const DATA_COLLECT_SLEEP = 2000; const DATA_COLLECT_SLEEP = 2000;
const PURGE_SLEEP = 60000;
const PURGE_TEASENSE_SLEEP = 1000;
interface DataPoint { type DataPoint = {
id: string;
name: string; name: string;
value: number; value: number;
timestamp: Date; timestamp: Date | null;
}; };
const db = createDB(); const app = admin.initializeApp({
credential: admin.credential.cert(serviceAccount as ServiceAccount),
databaseURL: process.env.DATABASE_URL ?? '',
});
const dataPointsTable = createTable<DataPoint>(db, 'dataPoints')(); const db = app.firestore();
(async () => { const saveDataPoint = async (name: string, value: number, noTimestamp?: boolean) => {
const app = express(); const docRef = db.collection('colligit').doc(name);
app.use( const values: DataPoint[] = [
'/', {
json(),
);
app.get('/:name', async (req: any, res: any) => {
const startTime = subHours(new Date(), 24);
const result = await many(dataPointsTable, {
where: {
name: req.params.name,
}
});
res.json(result);
});
app.listen(PORT);
console.log(`Listening to port ${PORT}`);
})();
let rainfallTimestamp = '';
const saveDataPoint = async (name: string, value: number) => {
await insert(dataPointsTable, {
id: uuid(),
name, name,
timestamp: (noTimestamp) ? null : new Date(),
value, value,
timestamp: new Date(), }
];
if (!noTimestamp) {
await docRef.set({
data: FieldValue.arrayUnion(...values),
}, { merge: true });
} else {
await docRef.set({
data: FieldValue.arrayUnion(...values),
}); });
}
} }
const collectData = async () => { const collectData = async () => {
@ -100,43 +79,13 @@ const collectData = async () => {
signal: AbortSignal.timeout(10000), signal: AbortSignal.timeout(10000),
}); });
const data: any = await response.json(); const data: any = await response.json();
await saveDataPoint('teasense', data.temperature); await saveDataPoint('teasense', data.temperature, true);
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
} }
purger5Sec();
setTimeout(() => collectData(), DATA_COLLECT_SLEEP); setTimeout(() => collectData(), DATA_COLLECT_SLEEP);
}; };
const purger = async () => {
const startTime = subHours(new Date(), 24);
await removeWhere(dataPointsTable, {
where: {
timestamp: {
lt: startTime,
},
},
});
};
const purger5Sec = async () => {
const startTime = subSeconds(new Date(), 5);
await removeWhere(dataPointsTable, {
where: {
name: {
in: ['teasense', 'soil_voltage'],
},
timestamp: {
lt: startTime,
},
},
});
};
setTimeout(() => collectData(), DATA_COLLECT_SLEEP); setTimeout(() => collectData(), DATA_COLLECT_SLEEP);
setInterval(() => purger(), PURGE_SLEEP);
// setInterval(() => purger5Sec(), PURGE_TEASENSE_SLEEP);

View File

@ -25,7 +25,7 @@
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */ /* Modules */
"module": "ES2022", /* Specify what module code is generated. */ "module": "ESNext", /* Specify what module code is generated. */
"rootDir": "./src", /* Specify the root folder within your source files. */ "rootDir": "./src", /* Specify the root folder within your source files. */
"moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
@ -35,7 +35,7 @@
// "types": [], /* Specify type package names to be included without being referenced in a source file. */ // "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
// "resolveJsonModule": true, /* Enable importing .json files. */ "resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */ // "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */ /* JavaScript Support */