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, 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 function getMonthFromString(mon) { var d = Date.parse(mon + "1, 2012"); if (!isNaN(d)) { return new Date(d).getMonth() + 1; } return -1; } async function getLocation() { const location = await locationModel.findAll(); return location; } async function addLocation(name, added_by, description) { const location = await locationModel.create({ name: name, added_by: added_by, description: description, }); } async function updateLocation(id, name, added_by, description) { const location = await locationModel.update( { name: name, added_by: added_by, description: description, }, { where: { id: id, }, } ); } async function deleteLocation(id) { //delete by id const location = await locationModel.destroy({ where: { id: id, }, }); } async function getLocationById(id) { const location = await locationModel.findAll({ where: { id: id, }, }); return location; } async function getSensor() { const sensor = await sensorModel.findAll(); return sensor; console.error(error); } async function addSensor( sensorname, added_by, mac_address, description, location ) { const sensor = await sensorModel.create({ name: sensorname, added_by: added_by, mac_address: mac_address, description: description, location: location, }); } async function updateSensor( id, sensorname, added_by, mac_address, description, location ) { const sensor = await sensorModel.update( { name: sensorname, added_by: added_by, mac_address: mac_address, description: description, location: location, }, { where: { id: id, }, } ); } async function deleteSensor(id) { //delete by id const sensor = await sensorModel.destroy({ where: { id: id, }, }); console.error(error); } async function getSensorById(id) { const sensor = await sensorModel.findAll({ where: { id: id, }, }); return sensor; } async function getSensorData() { const sensorData = await sensorDataModel.findAll(); return sensorData; } async function addSensorData(id, id_sensor, id_location, sensordata) { const sensorData = await sensorDataModel.create({ id: id, sensorid: id_sensor, locationid: id_location, measurement: sensordata, }); } async function updateSensorData(id, id_sensor, id_location, sensordata) { const sensorData = await sensorDataModel.update( { ensorid: id_sensor, locationid: id_location, measurement: sensordata, }, { where: { id: id, }, } ); } async function deleteSensorData(id) { const sensorData = await sensorDataModel.destroy({ where: { id: id, }, }); } async function getSensorDataById(id) { const sensorData = await sensorDataModel.findAll({ where: { id: id, }, }); return sensorData; } var ormQuery = {}; var whereClause = {}; var whereDate = {}; const allowedQuery = [ "limit", "order", "year", "month", "week", "day", "hour", "minute", "sensorid", "locationid", ]; const validMonths = [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", ]; //handle buildfunc for query buildQuery = { limit: async function (queryString) { if (queryString.limit !== undefined) { ormQuery.limit = parseInt(queryString.limit); } }, order: async function (queryString) { if (queryString.order !== undefined) { ormQuery = { ...ormQuery, order: [["createdAt", queryString.order.toUpperCase()]], }; } }, year: async function (queryString) { if (queryString.year !== undefined) { //whereclause assign a value whereClause.year = sequelize.where( sequelize.fn("YEAR", sequelize.col("createdAt")), queryString.year ); } }, month: async function (queryString) { if (queryString.month !== undefined) { if (validMonths.includes(queryString.month)) { whereClause.month = sequelize.where( sequelize.fn("MONTH", sequelize.col("createdAt")), queryString.month ); } else { whereClause.month = sequelize.where( sequelize.fn("MONTH", sequelize.col("createdAt")), queryString.month ); } } }, week: async function (queryString) { if (queryString.week !== undefined) { whereClause.week = sequelize.where( sequelize.fn("WEEK", sequelize.col("createdAt")), queryString.week ); } }, day: async function (queryString) { if (queryString.day !== undefined) { whereClause.day = sequelize.where( sequelize.fn("DAY", sequelize.col("createdAt")), queryString.day ); } }, hour: async function (queryString) { if (queryString.hour !== undefined) { whereClause.hour = sequelize.where( sequelize.fn("HOUR", sequelize.col("createdAt")), queryString.hour ); } }, minute: async function (queryString) { if (queryString.minute !== undefined) { whereClause.minute = sequelize.where( sequelize.fn("MINUTE", sequelize.col("createdAt")), queryString.minute ); } }, 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 = { limit: async function (queryString) { if (queryString.limit !== undefined) { ormQuery.limit = parseInt(queryString.limit); } }, 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) { if (queryString.pagesize || queryString.page) { //https://blog.bitsrc.io/pagination-with-sequelize-explained-83054df6e041 //pass pageSize taken from page=4 or default to 50 queryString.pagesize = queryString.pagesize || 50; let offset = (queryString.page || 0) * queryString.pagesize; queryString.limit = queryString.pagesize; //reset keys in whereClause and ormQuery. else it will keep appending to the previous query ormQuery = {}; whereClause = {}; 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, //https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#limits-and-pagination offset: parseInt(offset), //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], }, //only use where clause to lookup based on condition that i put into whereClause ...ormQuery, }); } } else { //reset keys in whereClause and ormQuery. else it will keep appending to the previous query ormQuery = {}; whereClause = {}; 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. //https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#examples-with-opand-and-opor where: { [Op.and]: [whereClause], }, //only use where clause to lookup based on condition that i put into whereClause ...ormQuery, }); } } } async function getDatabyRange(queryString) { if (queryString.pagesize || queryString.page) { //https://blog.bitsrc.io/pagination-with-sequelize-explained-83054df6e041 //pass pageSize taken from page=4 or default to 50 queryString.pagesize = queryString.pagesize || 50; let offset = (queryString.page || 0) * queryString.pagesize; queryString.limit = queryString.pagesize; 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, offset: offset, //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"; } } else { 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, addLocation, updateLocation, deleteLocation, getLocationById, getSensor, addSensor, updateSensor, deleteSensor, getSensorById, getSensorData, addSensorData, updateSensorData, deleteSensorData, getSensorDataById, getData, getDatabyRange, };