Update to push to firestore
This commit is contained in:
parent
c217a807a7
commit
a865e2a89a
1
.gitignore
vendored
1
.gitignore
vendored
@ -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
|
||||||
|
6963
package-lock.json
generated
6963
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
16
package.json
16
package.json
@ -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"
|
||||||
}
|
}
|
||||||
|
105
src/index.ts
105
src/index.ts
@ -1,71 +1,50 @@
|
|||||||
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),
|
||||||
const dataPointsTable = createTable<DataPoint>(db, 'dataPoints')();
|
databaseURL: process.env.DATABASE_URL ?? '',
|
||||||
|
|
||||||
(async () => {
|
|
||||||
const app = express();
|
|
||||||
|
|
||||||
app.use(
|
|
||||||
'/',
|
|
||||||
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);
|
const db = app.firestore();
|
||||||
});
|
|
||||||
|
|
||||||
app.listen(PORT);
|
const saveDataPoint = async (name: string, value: number, noTimestamp?: boolean) => {
|
||||||
console.log(`Listening to port ${PORT}`);
|
const docRef = db.collection('colligit').doc(name);
|
||||||
})();
|
|
||||||
|
|
||||||
let rainfallTimestamp = '';
|
const values: DataPoint[] = [
|
||||||
|
{
|
||||||
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 () => {
|
||||||
if (RAIN_GAUGE_ENDPOINT && RAIN_GAUGE_ENDPOINT.trim() !== '') {
|
if (RAIN_GAUGE_ENDPOINT && RAIN_GAUGE_ENDPOINT.trim() !== '') {
|
||||||
@ -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);
|
|
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user