Merge branch 'main' into login

This commit is contained in:
newtbot 2024-01-12 02:43:51 +08:00
commit 41336df568
8 changed files with 655 additions and 318 deletions

View File

@ -26,88 +26,3 @@ log_dest file /var/log/mosquitto/mosquitto.log
https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-the-mosquitto-mqtt-messaging-broker-on-ubuntu-18-04
let ormQuery = {};
let whereClause = {};
//let whereNest = {};
//let whereDate = {};
buildFuncs = {
month: function(query){
const validMonths = [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
];
if (validMonths.includes(query.month)) {
whereClause = {
where: sequelize.where(
sequelize.fn("MONTH", sequelize.col("createdAt")),
query.month
),
};
} else {
query.month = getMonthFromString(query.month);
whereClause = {
where: sequelize.where(
sequelize.fn("MONTH", sequelize.col("createdAt")),
query.month
),
};
}
},
week: function(query){
whereClause.week = sequelize.where(
sequelize.fn("WEEK", sequelize.col("createdAt")),
query.week
);
},
sensorid: function (query){
whereClause.sensorid = sequelize.where(
sequelize.col("sensorid"),
query.sensorid
);
}
}
function getData(queryString)
for(let query in queryString){
if(buildFuncs[query]); buildFuncs[query](queryString)
if (!whereClause) {
return await sensorDataModel.findAll(ormQuery);
} else if (whereClause) {
console.log(whereClause);
//console.log(whereNest);
//console.log(whereDate);
console.log(query);
console.log(ormQuery);
return await sensorDataModel.findAll({
//limit default value if query.limit is undefined or not provided
limit: query.limit,
//The operators Op.and, Op.or and Op.not can be used to create arbitrarily complex nested logical comparisons.
//https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#examples-with-opand-and-opor
where: {
//[Op.and]: [whereNest, whereClause],
[Op.and]: [whereClause],
createdAt: {
//https://stackoverflow.com/questions/43115151/sequelize-query-to-find-all-records-that-falls-in-between-date-range
[Op.between]: [whereClause.startdate, whereClause.enddate],
},
},
//only use where clause to lookup based on condition that i put into whereClause
...ormQuery,
});
}
}
}

View File

@ -2,7 +2,7 @@ const { sequelize } = require("../../Database/mySql.js");
const { locationModel } = require("../../Database/model/locationModel.js");
const { sensorModel } = require("../../Database/model/sensorModel.js");
const { sensorDataModel } = require("../../Database/model/sensorDataModel.js");
const { Op } = require("sequelize");
const { Op, Sequelize } = require("sequelize");
//helper function to convert month name to month number
//https://stackoverflow.com/questions/13566552/easiest-way-to-convert-month-name-to-month-number-in-js-jan-01
@ -172,6 +172,19 @@ async function getSensorDataById(id) {
}
var ormQuery = {};
var whereClause = {};
var whereDate = {};
const allowedQuery = [
"limit",
"order",
"year",
"month",
"week",
"day",
"hour",
"minute",
"sensorid",
"locationid",
];
const validMonths = [
"1",
"2",
@ -211,16 +224,13 @@ buildQuery = {
}
},
month: async function (queryString) {
console.log("queryString month:", queryString.month, queryString);
if (queryString.month !== undefined) {
console.log("queryString month:", "i should not be here");
if (validMonths.includes(queryString.month)) {
whereClause.month = sequelize.where(
sequelize.fn("MONTH", sequelize.col("createdAt")),
queryString.month
);
} else {
queryString.month = getMonthFromString(queryString.month);
whereClause.month = sequelize.where(
sequelize.fn("MONTH", sequelize.col("createdAt")),
queryString.month
@ -260,26 +270,444 @@ buildQuery = {
);
}
},
sensorid: async function (queryString) {
if (queryString.sensorid !== undefined) {
whereClause.sensorid = sequelize.where(
sequelize.col("sensorid"),
queryString.sensorid
);
}
},
locationid: async function (queryString) {
if (queryString.locationid !== undefined) {
whereClause.locationid = sequelize.where(
sequelize.col("locationid"),
queryString.locationid
);
}
},
psi: async function (queryString) {
if (queryString.psi !== undefined && queryString.psi === "highest") {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[sequelize.literal("JSON_EXTRACT(measurement, '$.psi')"), "psi"],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("psi"), "DESC"]],
limit: 10,
};
}
if (queryString.psi !== undefined && queryString.psi === "lowest") {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[sequelize.literal("JSON_EXTRACT(measurement, '$.psi')"), "psi"],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("psi"), "ASC"]],
limit: 10,
};
}
},
co: async function (queryString) {
if (queryString.co !== undefined && queryString.co === "highest") {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[sequelize.literal("JSON_EXTRACT(measurement, '$.co')"), "co"],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("co"), "DESC"]],
limit: 10,
};
}
if (queryString.co !== undefined && queryString.co === "lowest") {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[sequelize.literal("JSON_EXTRACT(measurement, '$.co')"), "co"],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("co"), "ASC"]],
limit: 10,
};
}
},
o3: async function (queryString) {
if (queryString.o3 !== undefined && queryString.o3 === "highest") {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[sequelize.literal("JSON_EXTRACT(measurement, '$.o3')"), "o3"],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("o3"), "DESC"]],
limit: 10,
};
}
if (queryString.o3 !== undefined && queryString.o3 === "lowest") {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[sequelize.literal("JSON_EXTRACT(measurement, '$.o3')"), "o3"],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("o3"), "ASC"]],
limit: 10,
};
}
},
no2: async function (queryString) {
if (queryString.no2 !== undefined && queryString.no2 === "highest") {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[sequelize.literal("JSON_EXTRACT(measurement, '$.no2')"), "no2"],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("no2"), "DESC"]],
limit: 10,
};
}
if (queryString.no2 !== undefined && queryString.no2 === "lowest") {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[sequelize.literal("JSON_EXTRACT(measurement, '$.no2')"), "no2"],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("no2"), "ASC"]],
limit: 10,
};
}
},
so2: async function (queryString) {
if (queryString.so2 !== undefined && queryString.so2 === "highest") {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[sequelize.literal("JSON_EXTRACT(measurement, '$.so2')"), "so2"],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("so2"), "DESC"]],
limit: 10,
};
}
if (queryString.so2 !== undefined && queryString.so2 === "lowest") {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[sequelize.literal("JSON_EXTRACT(measurement, '$.so2')"), "so2"],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("so2"), "ASC"]],
limit: 10,
};
}
},
humidity: async function (queryString) {
if (
queryString.humidity !== undefined &&
queryString.humidity === "highest"
) {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[
sequelize.literal("JSON_EXTRACT(measurement, '$.humidity')"),
"humidity",
],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("humidity"), "DESC"]],
limit: 10,
};
}
if (
queryString.humidity !== undefined &&
queryString.humidity === "lowest"
) {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[
sequelize.literal("JSON_EXTRACT(measurement, '$.humidity')"),
"humidity",
],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("humidity"), "ASC"]],
limit: 10,
};
}
},
windspeed: async function (queryString) {
if (
queryString.windspeed !== undefined &&
queryString.windspeed === "highest"
) {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[
sequelize.literal("JSON_EXTRACT(measurement, '$.windspeed')"),
"windspeed",
],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("windspeed"), "DESC"]],
limit: 10,
};
}
if (
queryString.windspeed !== undefined &&
queryString.windspeed === "lowest"
) {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[
sequelize.literal("JSON_EXTRACT(measurement, '$.windspeed')"),
"windspeed",
],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("windspeed"), "ASC"]],
limit: 10,
};
}
},
temperature: async function (queryString) {
if (
queryString.temperature !== undefined &&
queryString.temperature === "highest"
) {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[
sequelize.literal("JSON_EXTRACT(measurement, '$.temperature')"),
"temperature",
],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("temperature"), "DESC"]],
limit: 10,
};
}
if (
queryString.temperature !== undefined &&
queryString.temperature === "lowest"
) {
ormQuery = {
attributes: [
"id",
"sensorid",
"locationid",
[
sequelize.literal("JSON_EXTRACT(measurement, '$.temperature')"),
"temperature",
],
"createdAt",
],
group: ["id", "sensorid", "locationid"],
order: [[sequelize.literal("temperature"), "ASC"]],
limit: 10,
};
}
},
//average
avg: async function (queryString) {
if (queryString.avg !== undefined) {
ormQuery = {
attributes: [
//round to 2 decimal places
[
sequelize.fn(
"ROUND",
sequelize.fn(
"AVG",
Sequelize.literal(
`JSON_EXTRACT(measurement, '$.${queryString.avg}')`
)
),
2
),
"avg of " + queryString.avg,
],
],
};
}
},
sum: async function (queryString) {
if (queryString.sum !== undefined) {
ormQuery = {
attributes: [
[
sequelize.fn(
"SUM",
Sequelize.literal(
`JSON_EXTRACT(measurement, '$.${queryString.sum}')`
)
),
"sum of " + queryString.sum,
],
],
};
}
},
//total number of records
total: async function (queryString) {
if (queryString.total !== undefined) {
ormQuery = {
attributes: [
[sequelize.fn("COUNT", sequelize.col("id")), "total id / records"],
],
};
}
},
};
buildFunc = {
startdate: async function (queryString) {
if (queryString.startdate !== undefined) {
whereDate.startdate = new Date(queryString.startdate);
}
},
enddate: async function (queryString) {
if (queryString.enddate !== undefined) {
whereDate.enddate = new Date(queryString.enddate);
}
},
//total by startdate and enddate
total: async function (queryString) {
if (queryString.total !== undefined) {
ormQuery = {
attributes: [
[sequelize.fn("COUNT", sequelize.col("id")), "total id / records"],
],
};
}
},
//average
avg: async function (queryString) {
if (queryString.avg !== undefined) {
ormQuery = {
attributes: [
//round to 2 decimal places
[
sequelize.fn(
"ROUND",
sequelize.fn(
"AVG",
Sequelize.literal(
`JSON_EXTRACT(measurement, '$.${queryString.avg}')`
)
),
2
),
"avg of " + queryString.avg,
],
],
};
}
},
sum: async function (queryString) {
if (queryString.sum !== undefined) {
ormQuery = {
attributes: [
[
sequelize.fn(
"SUM",
Sequelize.literal(
`JSON_EXTRACT(measurement, '$.${queryString.sum}')`
)
),
"sum of " + queryString.sum,
],
],
};
}
},
//total number of records
total: async function (queryString) {
if (queryString.total !== undefined) {
ormQuery = {
attributes: [
[sequelize.fn("COUNT", sequelize.col("id")), "total id / records"],
],
};
}
},
};
async function getData(queryString) {
// reset keys...
//reset keys in whereClause and ormQuery. else it will keep appending to the previous query
ormQuery = {};
whereClause = {};
for (let query in queryString) {
console.log(queryString);
console.log(query);
console.log(whereClause);
//console.log(ormQuery);
whereDate = {};
for (let query in queryString) {
if (buildQuery[query]) {
await buildQuery[query](queryString);
}
}
if (!whereClause) {
return await sensorDataModel.findAll(ormQuery);
} else if (whereClause) {
console.log(whereClause);
console.log(ormQuery);
console.log(whereDate);
return await sensorDataModel.findAll({
limit: queryString.limit || 1000000,
//The operators Op.and, Op.or and Op.not can be used to create arbitrarily complex nested logical comparisons.
@ -293,11 +721,32 @@ async function getData(queryString) {
}
}
async function getAverage(query) {}
/*
*/
async function getDatabyRange(queryString) {
whereDate = {};
for (let query in queryString) {
if (buildFunc[query]) {
await buildFunc[query](queryString);
}
}
if (whereClause) {
console.log(ormQuery);
console.log(whereDate);
return await sensorDataModel.findAll({
limit: queryString.limit || 1000000,
//The operators Op.and, Op.or and Op.not can be used to create arbitrarily complex nested logical comparisons.
//https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#examples-with-opand-and-opor
where: {
createdAt: {
[Op.between]: [whereDate.startdate, whereDate.enddate],
},
},
//only use where clause to lookup based on condition that i put into whereClause
...ormQuery,
});
} else {
return "Invalid query";
}
}
module.exports = {
getLocation,
@ -316,5 +765,6 @@ module.exports = {
deleteSensorData,
getSensorDataById,
getData,
getDatabyRange,
getAverage,
};

View File

@ -115,4 +115,18 @@ POST /api/v0/seed/sensordata
2) nextDataRow(lastRow, interval)
3) seedSensorData({post object from abovr})
function randomizeDataPoint(value, delta, maxDelta){
// https://stackoverflow.com/a/36756480
delta = Math.random() < 0.9 ? delta : maxDelta
return Math.floor(Math.random() * ((value+delta) - Math.abs(delta-value)) + Math.abs(delta-value));
}
let count = 0
let currentValue = 85
while(count <50){
count++
console.log(currentValue)
currentValue = randomizeDataPoint(currentValue, 2, 5)
}
*/

View File

@ -7,6 +7,7 @@ const {
deleteSensorData,
getSensorDataById,
getData,
getDatabyRange,
getdataFilter,
getAverage,
} = require("../functions/apiDatabase.js");
@ -60,6 +61,7 @@ router.delete("/delete", async (req, res, next) => {
*/
router.get("/data", async (req, res, next) => {
try {
console.log(req.query);
const data = await getData(req.query);
res.status(200).json(data);
@ -69,64 +71,20 @@ router.get("/data", async (req, res, next) => {
}
});
/*
router.get("/filter", async (req, res, next) => {
try {
const query = {
limit: req.query.limit,
psi: req.query.psi,
co: req.query.co,
o3: req.query.o3,
no2: req.query.no2,
so2: req.query.so2,
humidity: req.query.humidity,
windspeed: req.query.windspeed,
temperature: req.query.temperature,
//sensorid and locationid
};
const data = await getdataFilter(query);
//date range
router.get("/range", async (req, res, next) => {
try {
console.log(req.query);
const data = await getDatabyRange(req.query);
res.status(200).json(data);
} catch (error) {
console.error(error);
next(error);
}
});
*/
//average
router.get("/average", async (req, res, next) => {
try {
const query = {
psi: req.query.psi,
co: req.query.co,
o3: req.query.o3,
no2: req.query.no2,
so2: req.query.so2,
humidity: req.query.humidity,
windspeed: req.query.windspeed,
temperature: req.query.temperature,
//daily
day: req.query.day,
//hourly
hour: req.query.hour,
//weekly
week: req.query.week,
//monthly
month: req.query.month,
//yearly
year: req.query.year,
};
const data = await getAverage(query);
res.status(200).json(data);
} catch (error) {
console.error(error);
next(error);
}
} catch (error) {
console.error(error);
next(error);
}
});
router.get("/:id", async (req, res, next) => {
try {
const sensor = await getSensorDataById(req.params.id);
@ -138,26 +96,4 @@ router.get("/:id", async (req, res, next) => {
});
module.exports = router;
/*
**Aggregate Sensor Data (e.g., Average PSI):**
- **Route:** `GET /api/v0/sensor-data/aggregate`
- **Query Parameter:** `metric` (e.g., `psi`, `co`, `o3`)
- **Description:** Calculate aggregate metrics for the specified parameter.
*/
/*
"measurement": {
"co": 8,
"o3": 89,
"no2": 31,
"psi": 34,
"so2": 17,
"humidity": 86,
"windspeed": 10,
"temperature": 26
},
*/

4
api.MD
View File

@ -150,7 +150,9 @@ Hour = 1 or wtv
//strong optional chaining
curl 'http://localhost/api/v0/sensor-data/data?year=2023&month=1&week=1&day=1&sensorid=1&locationid=1'
http://localhost/api/v0/sensor-data/data?startdate=2023-01-01T00:00:00.000&enddate=2023-01-03T&sensorid=1&locationid=1
//get specific data
http://localhost/api/v0/sensor-data/filter?windspeed=highest&limit=1

177
package-lock.json generated
View File

@ -3,8 +3,47 @@
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@mapbox/node-pre-gyp": {
"packages": {
"": {
"name": "mp",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"bcrypt": "^5.1.1",
"body-parser": "^1.20.2",
"dotenv": "^16.3.1",
"ejs": "^3.1.9",
"express": "^4.18.2",
"express-session": "^1.17.3",
"express-validator": "^7.0.1",
"helmet": "^7.1.0",
"moment": "^2.30.1",
"mqtt": "^5.3.3",
"mysql2": "^3.6.5",
"nodemailer": "^6.9.7",
"otp-generator": "^4.0.1",
"otplib": "^12.0.1",
"qrcode": "^1.5.3",
"sanitize-html": "^2.11.0",
"sequelize": "^6.35.2",
"validator": "^13.11.0"
},
"devDependencies": {
"nodemon": "^3.0.2"
}
},
"node_modules/@babel/runtime": {
"version": "7.23.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.7.tgz",
"integrity": "sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@mapbox/node-pre-gyp": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
"integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
@ -123,6 +162,19 @@
"color-convert": "^2.0.1"
}
},
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dev": true,
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"engines": {
"node": ">= 8"
}
},
"aproba": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz",
@ -173,7 +225,17 @@
"node-addon-api": "^5.0.0"
}
},
"body-parser": {
"node_modules/bl": {
"version": "6.0.10",
"resolved": "https://registry.npmjs.org/bl/-/bl-6.0.10.tgz",
"integrity": "sha512-F14DFhDZfxtVm2FY0k9kG2lWAwzZkO9+jX3Ytuoy/V0E1/5LBuBzzQHXAjqpxXEDIpmTPZZf5GVIGPQcLxFpaA==",
"dependencies": {
"buffer": "^6.0.3",
"inherits": "^2.0.4",
"readable-stream": "^4.2.0"
}
},
"node_modules/body-parser": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
@ -215,7 +277,35 @@
"balanced-match": "^1.0.0"
}
},
"bytes": {
"node_modules/buffer": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
}
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
@ -244,7 +334,7 @@
"supports-color": "^7.1.0"
}
},
"chownr": {
"node_modules/chownr": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
@ -604,7 +694,7 @@
}
}
},
"finalhandler": {
"node_modules/finalhandler": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
"integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
@ -675,7 +765,7 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"function-bind": {
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
@ -733,7 +823,7 @@
"path-is-absolute": "^1.0.0"
}
},
"gopd": {
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
@ -815,9 +905,31 @@
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3"
},
"engines": {
"node": ">=0.10.0"
}
},
"inflection": {
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/inflection": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz",
"integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw=="
@ -841,12 +953,12 @@
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
},
"is-fullwidth-code-point": {
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"is-plain-object": {
"node_modules/is-plain-object": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="
@ -1080,7 +1192,7 @@
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.7.tgz",
"integrity": "sha512-rUtR77ksqex/eZRLmQ21LKVH5nAAsVicAtAYudK7JgwenEDZ0UIQ1adUGqErz7sMkWYxWTTU1aeP2Jga6WQyJw=="
},
"nopt": {
"node_modules/nopt": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
"integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
@ -1088,7 +1200,7 @@
"abbrev": "1"
}
},
"npmlog": {
"node_modules/npmlog": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
"integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
@ -1201,7 +1313,7 @@
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
},
"pngjs": {
"node_modules/pngjs": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
"integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="
@ -1225,7 +1337,7 @@
"ipaddr.js": "1.9.1"
}
},
"qrcode": {
"node_modules/qrcode": {
"version": "1.5.3",
"resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz",
"integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==",
@ -1265,7 +1377,32 @@
"unpipe": "1.0.0"
}
},
"require-directory": {
"node_modules/readable-stream": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz",
"integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==",
"dependencies": {
"abort-controller": "^3.0.0",
"buffer": "^6.0.3",
"events": "^3.3.0",
"process": "^0.11.10",
"string_decoder": "^1.3.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
}
},
"node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
},
"node_modules/reinterval": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz",
"integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ=="
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
@ -1441,7 +1578,7 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
},
"source-map-js": {
"node_modules/source-map-js": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
@ -1515,7 +1652,7 @@
"resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz",
"integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA=="
},
"toidentifier": {
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
@ -1525,7 +1662,7 @@
"resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz",
"integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg=="
},
"tr46": {
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
@ -1547,7 +1684,7 @@
"random-bytes": "~1.0.0"
}
},
"undici-types": {
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="

View File

@ -35,5 +35,8 @@
"sanitize-html": "^2.11.0",
"sequelize": "^6.35.2",
"validator": "^13.11.0"
},
"devDependencies": {
"nodemon": "^3.0.2"
}
}

120
test.js
View File

@ -1,120 +0,0 @@
let ormQuery = {};
let whereClause = {};
const validMonths = [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"11",
"12",
];
//handle buildfunc for query
buildQuery = {
year: async function (query) {
if (query.year !== undefined) {
//whereclause assign a value
whereClause.year = sequelize.where(
sequelize.fn("YEAR", sequelize.col("createdAt")),
query.year
);
}
},
};
/*
function getData(queryString)
for(let query in queryString){
if(buildFuncs[query]); buildFuncs[query](queryString)
if (!whereClause) {
return await sensorDataModel.findAll(ormQuery);
} else if (whereClause) {
if (query.year) {
whereClause.year = sequelize.where(
sequelize.fn("YEAR", sequelize.col("createdAt")),
query.year
);
}
*/
async function getData(query) {
for (let queryString in query) {
console.log(query);
console.log(queryString);
console.log(whereClause);
console.log(ormQuery);
if (buildQuery[queryString]);
await buildQuery[queryString](query);
if (!whereClause) {
return await sensorDataModel.findAll(ormQuery);
} else if (whereClause) {
return await sensorDataModel.findAll({
limit: query.limit || 10,
//The operators Op.and, Op.or and Op.not can be used to create arbitrarily complex nested logical comparisons.
//https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#examples-with-opand-and-opor
where: {
[Op.and]: [whereClause],
createdAt: {
//https://stackoverflow.com/questions/43115151/sequelize-query-to-find-all-records-that-falls-in-between-date-range
[Op.between]: [whereClause.startdate, whereClause.enddate],
},
},
//only use where clause to lookup based on condition that i put into whereClause
...ormQuery,
});
}
}
}
async function getData(query) {
for (let queryString in query) {
console.log(query);
console.log(queryString);
console.log(whereClause);
console.log(ormQuery);
if (buildQuery[queryString]);
await buildQuery[queryString](query);
if (!whereClause) {
return await sensorDataModel.findAll(ormQuery);
} else if (whereClause) {
return await sensorDataModel.findAll({
limit: query.limit || 10,
//The operators Op.and, Op.or and Op.not can be used to create arbitrarily complex nested logical comparisons.
//https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#examples-with-opand-and-opor
where: {
[Op.and]: [whereClause],
createdAt: {
//https://stackoverflow.com/questions/43115151/sequelize-query-to-find-all-records-that-falls-in-between-date-range
[Op.between]: [whereClause.startdate, whereClause.enddate],
},
},
//only use where clause to lookup based on condition that i put into whereClause
...ormQuery,
});
}
}
}
query.hour ||
query.sensorid ||
query.locationid ||
query.startdate ||
query.enddate