From ce2b776920df4aa9264359239afd2ba5966d7759 Mon Sep 17 00:00:00 2001 From: newtbot Date: Tue, 9 Jan 2024 02:01:59 +0800 Subject: [PATCH] WIP routes data --- Documentation/iot-data-output.txt | 31 +++-- Web-Server/functions/APIDatabase.js | 85 ++++++++++++-- Web-Server/routes/SensorData.js | 171 +++++++++++++++++++--------- api.MD | 2 + 4 files changed, 212 insertions(+), 77 deletions(-) diff --git a/Documentation/iot-data-output.txt b/Documentation/iot-data-output.txt index a524fc2..2977be5 100644 --- a/Documentation/iot-data-output.txt +++ b/Documentation/iot-data-output.txt @@ -1,12 +1,19 @@ -{ - psi: '34', - humidity: '11%', - o3: '326ppm', - no2: '445ppm', - so2: '511ppm', - co: '16ppm', - temperature: '25°C', - windspeed: '2km/h', - time: '2023-12-21 14:24:44', - region: 'east' -} + + { + "id": 1, + "sensorid": 1, + "locationid": 1, + "measurement": { + "co": 8, + "o3": 89, + "no2": 31, + "psi": 34, + "so2": 17, + "humidity": 86, + "windspeed": 10, + "temperature": 26 + }, + "createdAt": "2023-01-01T16:00:00.000Z", + "updatedAt": "2024-01-05T11:34:10.000Z" + }, + \ No newline at end of file diff --git a/Web-Server/functions/APIDatabase.js b/Web-Server/functions/APIDatabase.js index deee89a..e884e4f 100644 --- a/Web-Server/functions/APIDatabase.js +++ b/Web-Server/functions/APIDatabase.js @@ -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, where, or } = 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 @@ -175,6 +175,7 @@ async function getData(query) { let ormQuery = {}; let whereClause = {}; let whereNest = {}; + let whereDate = {}; if (query.limit !== undefined && query.order !== undefined) ormQuery = { @@ -194,7 +195,11 @@ async function getData(query) { query.hour || query.minute || query.sensorid || - query.locationid + query.locationid || + query.startdate || + query.enddate + + //get specific data like psi or wtv ) { if (query.limit !== undefined && query.order !== undefined) ormQuery = { @@ -266,6 +271,15 @@ async function getData(query) { query.minute ); } + if (query.startdate) { + let startdate = new Date(query.startdate); + whereDate.startdate = startdate; + } + if (query.enddate) { + let enddate = new Date(query.enddate); + whereDate.enddate = enddate; + } + if (query.sensorid) { whereNest.sensorid = sequelize.where( sequelize.col("sensorid"), @@ -380,32 +394,84 @@ async function getData(query) { }; } - //get specific data like psi or wtv - - //range of date values - if (!whereClause) { return await sensorDataModel.findAll(ormQuery); - } else { + } else if (whereClause && whereNest) { console.log(whereClause); console.log(whereNest); + console.log(whereDate); console.log(query); console.log(ormQuery); + return await sensorDataModel.findAll({ //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], + createdAt: { + //https://stackoverflow.com/questions/43115151/sequelize-query-to-find-all-records-that-falls-in-between-date-range + [Op.between]: [whereDate.startdate, whereDate.enddate], + }, }, //only use where clause to lookup based on condition that i put into whereClause - //where: whereClause, ...ormQuery, }); } } -/* +async function getdataFilter(query) { + let ormQuery = {}; + //get highest and lowest data of measurement from all data + if (query.psi !== undefined && query.psi === "highest") { + ormQuery = { + where: sequelize.where( + sequelize.fn("JSON_EXTRACT", sequelize.col("measurement"), "$.psi"), + //sequelize.fn('JSON_EXTRACT', sequelize.col('aa.bb.field'), sequelize.literal(`'$.attr'`)) + sequelize.literal(`'$$.type'`), + + //max value of psi + sequelize.fn("MAX", sequelize.col("measurement.psi")) + ), + }; + } + + console.log(ormQuery); + return await sensorDataModel.findAll(ormQuery); +} + +/* +sequelize.fn('JSON_EXTRACT', sequelize.col('aa.bb.field'), sequelize.literal(`'$.attr'`)) + + else if (query.hour !== undefined) { + ormQuery = { + where: sequelize.where( + sequelize.fn("HOUR", sequelize.col("createdAt")), + query.hour + ), + ...ormQuery, + }; + } + + + +*/ + +/*' ormQuery = { + order: [sequelize.fn("max", sequelize.col("measurement.psi::int"))], + limit: 1, + }; + sequelize.literal('(SELECT MAX(`measurement`->>"$.psi") FROM `sensorData`)'), + 'max_psi' + if (query.highest) { + //[sequelize.fn("max", sequelize.col("measurement.psi")), "max_psi"], + + ormQuery = { + attributes: [ + [sequelize.fn("max", sequelize.col("measurement")), "max"], + ], + }; + } */ @@ -426,4 +492,5 @@ module.exports = { deleteSensorData, getSensorDataById, getData, + getdataFilter, }; diff --git a/Web-Server/routes/SensorData.js b/Web-Server/routes/SensorData.js index d4d4bbe..6e897e8 100644 --- a/Web-Server/routes/SensorData.js +++ b/Web-Server/routes/SensorData.js @@ -1,13 +1,13 @@ const { sequelize } = require("../../Database/mySql.js"); const { sensorDataModel } = require("../../Database/model/sensorDataModel.js"); const { - getSensorData, - addSensorData, - updateSensorData, - deleteSensorData, - getSensorDataById, - getData, - + getSensorData, + addSensorData, + updateSensorData, + deleteSensorData, + getSensorDataById, + getData, + getdataFilter, } = require("../functions/apiDatabase.js"); const express = require("express"); @@ -26,9 +26,9 @@ router.get("/", async (req, res, next) => { router.post("/new", async (req, res, next) => { try { - const { id, id_sensor, id_location, sensordata } = req.body; - await addSensorData(id , id_sensor , id_location , sensordata); - res.sendStatus(200).json({message: "SensorData " + id + " added" }); + const { id, id_sensor, id_location, sensordata } = req.body; + await addSensorData(id, id_sensor, id_location, sensordata); + res.sendStatus(200).json({ message: "SensorData " + id + " added" }); } catch (error) { console.error(error); next(error); @@ -37,9 +37,9 @@ router.post("/new", async (req, res, next) => { router.put("/update", async (req, res, next) => { try { - const { id , id_sensor , id_location , sensordata } = req.body; - await updateSensorData( id , id_sensor , id_location , sensordata ); - res.status(200).json({ message: "SensorData " + id + " updated" }); + const { id, id_sensor, id_location, sensordata } = req.body; + await updateSensorData(id, id_sensor, id_location, sensordata); + res.status(200).json({ message: "SensorData " + id + " updated" }); } catch (error) { console.error(error); next(error); @@ -47,55 +47,65 @@ router.put("/update", async (req, res, next) => { }); router.delete("/delete", async (req, res, next) => { - try { - const { id } = req.body; - await deleteSensorData(id); - res.status(200).json({ message: "SensorData " + id + " deleted" }); - } catch (error) { - console.error(error); - next(error); - } + try { + const { id } = req.body; + await deleteSensorData(id); + res.status(200).json({ message: "SensorData " + id + " deleted" }); + } catch (error) { + console.error(error); + next(error); + } }); - router.get("/data", async (req, res, next) => { try { - let query = { - //can be desc or asc - order: req.query.order, + let query = { + //can be desc or asc + order: req.query.order, - // number of data to be returned - limit: req.query.limit, + // number of data to be returned + limit: req.query.limit, - //can be sensorid, locationid - sensorid: req.query.sensorid, + //can be sensorid, locationid + sensorid: req.query.sensorid, - //can be sensorid, locationid - locationid: req.query.locationid, - //yearly - year: req.query.year, + //can be sensorid, locationid + locationid: req.query.locationid, + //yearly + year: req.query.year, - //monthly - month: req.query.month, + //monthly + month: req.query.month, - //weekly - week: req.query.week, + //weekly + week: req.query.week, - //daily - day: req.query.day, + //daily + day: req.query.day, - //hourly - hour: req.query.hour, + //hourly + hour: req.query.hour, - //minute - minute: req.query.minute, - + //minute + minute: req.query.minute, - }; - - const data = await getData(query); - res.status(200).json(data); - + //start date + startdate: req.query.startdate, + + //end date + enddate: req.query.enddate, + /* + //highest or lowest of psi, co, o3, no2, so2, humidity, windspeed, temperature + highest: req.query.highest, + + //highest or lowest of psi, co, o3, no2, so2, humidity, windspeed, temperature + lowest: req.query.lowest, + + */ + }; + + const data = await getData(query); + res.status(200).json(data); } catch (error) { console.error(error); next(error); @@ -103,14 +113,63 @@ router.get("/data", async (req, res, next) => { }); +router.get("/filter", 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, + }; + const data = await getdataFilter(query); + res.status(200).json(data); + } catch (error) { + console.error(error); + next(error); + } +}); + + + router.get("/:id", async (req, res, next) => { - try { - const sensor = await getSensorDataById(req.params.id); - res.status(200).json(sensor); - } catch (error) { - console.error(error); - next(error); - } + try { + const sensor = await getSensorDataById(req.params.id); + res.status(200).json(sensor); + } catch (error) { + console.error(error); + next(error); + } }); 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. + +**Filter Sensor Data by Measurement Values:** + +- **Route:** `GET /api/v0/sensor-data/filter` +- **Query Parameters:** `min_psi`, `max_psi`, `min_co`, `max_co`, etc. temp and humidity too +- **Description:** Retrieve sensor data entries within specified measurement value ranges. +*/ + +/* +"measurement": { + "co": 8, + "o3": 89, + "no2": 31, + "psi": 34, + "so2": 17, + "humidity": 86, + "windspeed": 10, + "temperature": 26 + }, + +*/ \ No newline at end of file diff --git a/api.MD b/api.MD index 8f8562e..0dc319a 100644 --- a/api.MD +++ b/api.MD @@ -153,4 +153,6 @@ 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 \ No newline at end of file