round2
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
const express = require("express");
|
||||
const { rateLimit } = require("express-rate-limit");
|
||||
const path = require("path");
|
||||
const app = express();
|
||||
const port = 3000;
|
||||
@ -8,6 +9,20 @@ const ejs = require("ejs");
|
||||
app.use(express.json());
|
||||
app.set("json spaces", 2);
|
||||
|
||||
//express-rate-limit stolen from docs
|
||||
const limiter = rateLimit({
|
||||
windowMs: 15 * 60 * 1000, // 15 minutes
|
||||
limit: 600, // Limit each IP to 100 requests per `window` (here, per 15 minutes).
|
||||
standardHeaders: 'draft-7', // draft-6: `RateLimit-*` headers; draft-7: combined `RateLimit` header
|
||||
legacyHeaders: false, // Disable the `X-RateLimit-*` headers.
|
||||
});
|
||||
|
||||
// Apply the rate limiting middleware to all requests.
|
||||
app.use(limiter);
|
||||
|
||||
//disable x-powered-by header for security reasons
|
||||
app.disable("x-powered-by");
|
||||
|
||||
// Set up the templating engine to build HTML for the front end.
|
||||
app.set("views", path.join(__dirname, "./views"));
|
||||
app.set("view engine", "ejs");
|
||||
@ -15,11 +30,9 @@ app.set("view engine", "ejs");
|
||||
// Have express server static content( images, CSS, browser JS) from the public
|
||||
app.use(express.static(path.join(__dirname, "./public")));
|
||||
|
||||
//middleware logic ( called by next() )
|
||||
const auth = require("./middleware/authChecker");
|
||||
|
||||
|
||||
//route logic
|
||||
app.use("/api/seed/v0" ,require("./routes/seed_route.js"));
|
||||
app.use("/api/v0", require("./routes/api_routes"));
|
||||
|
||||
//render logic
|
||||
|
@ -2,8 +2,6 @@
|
||||
const { Sequelize, DataTypes, Op } = require("sequelize");
|
||||
const { sequelize } = require("../mySql");
|
||||
const { userModel } = require("./userModel");
|
||||
const { generateUUID } = require("../../functions/generateUUID.js");
|
||||
const { hash, compareHash } = require("../../functions/bcrypt.js");
|
||||
|
||||
//sequelize.sync();
|
||||
const apikeyModel = sequelize.define(
|
||||
|
@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
const { Sequelize, DataTypes } = require("sequelize");
|
||||
const { sequelize } = require("../mySQL");
|
||||
const { sequelize } = require("../mySql");
|
||||
|
||||
//sequelize.sync();
|
||||
const api_log_Model = sequelize.define(
|
||||
@ -68,4 +68,6 @@ const api_log_Model = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
api_log_Model.sync()
|
||||
|
||||
module.exports = { api_log_Model };
|
||||
|
@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
const { Sequelize, DataTypes } = require("sequelize");
|
||||
const { sequelize } = require("../mySQL");
|
||||
const { sequelize } = require("../mySql");
|
||||
const { isAlphaNumericwithSpaces } = require('../../functions/validateData')
|
||||
|
||||
//sequelize.sync();
|
||||
@ -72,59 +72,6 @@ const locationModel = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
async function getLocation() {
|
||||
const location = await locationModel.findAll();
|
||||
return location;
|
||||
}
|
||||
locationModel.sync();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
locationModel,
|
||||
getLocation,
|
||||
addLocation,
|
||||
updateLocation,
|
||||
deleteLocation,
|
||||
getLocationById,
|
||||
};
|
||||
module.exports = { locationModel };
|
||||
|
@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
const { Sequelize, DataTypes } = require("sequelize");
|
||||
const { sequelize } = require("../mySQL");
|
||||
const { sequelize } = require("../mySql");
|
||||
const { locationModel } = require("./locationModel");
|
||||
const { sensorModel } = require("./sensorModel");
|
||||
const { isJson } = require('../../functions/validateData');
|
||||
@ -74,4 +74,6 @@ const sensorDataModel = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
sensorDataModel.sync()
|
||||
|
||||
module.exports = { sensorDataModel };
|
||||
|
@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
const { Sequelize, DataTypes } = require("sequelize");
|
||||
const { sequelize } = require("../mySQL");
|
||||
const { sequelize } = require("../mySql");
|
||||
const { locationModel } = require("./locationModel");
|
||||
const {
|
||||
isAlphaNumericwithSpaces,
|
||||
@ -107,4 +107,6 @@ const sensorModel = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
sensorModel.sync()
|
||||
|
||||
module.exports = { sensorModel };
|
||||
|
@ -112,4 +112,6 @@ const userModel = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
userModel.sync()
|
||||
|
||||
module.exports = { userModel };
|
||||
|
55
consumerWebsite/functions/location.js
Normal file
55
consumerWebsite/functions/location.js
Normal file
@ -0,0 +1,55 @@
|
||||
const {locationModel} = require("../database/model/locationModel");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getLocation,
|
||||
addLocation,
|
||||
updateLocation,
|
||||
deleteLocation,
|
||||
getLocationById,
|
||||
};
|
23
consumerWebsite/functions/logger.js
Normal file
23
consumerWebsite/functions/logger.js
Normal file
@ -0,0 +1,23 @@
|
||||
const { api_log_Model } = require("../database/model/apiLogModel.js");
|
||||
|
||||
|
||||
async function insertLogData(log) {
|
||||
try {
|
||||
api_log_Model.create({
|
||||
ip: log.ip,
|
||||
time: log.time,
|
||||
method: log.method,
|
||||
host: log.host,
|
||||
statusCode: log.statusCode,
|
||||
Responsesize: log.Responsesize,
|
||||
referrer: log.referrer,
|
||||
userAgent: log.userAgent,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
insertLogData,
|
||||
};
|
75
consumerWebsite/functions/sensor.js
Normal file
75
consumerWebsite/functions/sensor.js
Normal file
@ -0,0 +1,75 @@
|
||||
const {sensorModel} = require("../database/model/sensorModel");
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getSensor,
|
||||
addSensor,
|
||||
updateSensor,
|
||||
deleteSensor,
|
||||
};
|
724
consumerWebsite/functions/sensorData.js
Normal file
724
consumerWebsite/functions/sensorData.js
Normal file
@ -0,0 +1,724 @@
|
||||
const { sequelize } = require("../database/mySql.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 getSensorData() {
|
||||
const sensorData = await sensorDataModel.findAll();
|
||||
return sensorData;
|
||||
}
|
||||
|
||||
async function addSensorData(id_sensor, id_location, sensordata) {
|
||||
const sensorData = await sensorDataModel.create({
|
||||
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 {
|
||||
queryString.month = getMonthFromString(queryString.month)
|
||||
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 = {
|
||||
getSensorData,
|
||||
addSensorData,
|
||||
updateSensorData,
|
||||
deleteSensorData,
|
||||
getSensorDataById,
|
||||
getData,
|
||||
getDatabyRange,
|
||||
|
||||
};
|
@ -1,5 +1,27 @@
|
||||
var validator = require("validator");
|
||||
|
||||
const dateRegex = /^[A-Za-z]{3}, \d{2} [A-Za-z]{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/;
|
||||
|
||||
function isValidDateString(value) {
|
||||
return dateRegex.test(value);
|
||||
}
|
||||
|
||||
|
||||
function isMacAddress(value) {
|
||||
// Joi.string().regex(/^([0-9a-f]{2}-){5}([0-9a-f]{2})$/i).lowercase()
|
||||
//return validator.isMACAddress(value, { no_separators: true, eui: 48 });
|
||||
const macAddress = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/;
|
||||
const valid = macAddress.test(value);
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
function isNumber(value) {
|
||||
if (typeof value === "number") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function isAlphaNumericwithSpaces(value) {
|
||||
return validator.isAlphanumeric(value, ["en-US"], { ignore: " " });
|
||||
}
|
||||
@ -44,6 +66,8 @@ module.exports = {
|
||||
isAlphaNumericwithSpaces,
|
||||
isAlphaNumericWithSpacesAndDash,
|
||||
isJson,
|
||||
isAddress
|
||||
};
|
||||
|
||||
isAddress,
|
||||
isValidDateString,
|
||||
isMacAddress,
|
||||
isNumber,
|
||||
};
|
37
consumerWebsite/middleware/apiLogger.js
Normal file
37
consumerWebsite/middleware/apiLogger.js
Normal file
@ -0,0 +1,37 @@
|
||||
const { insertLogData } = require("../functions/logger.js");
|
||||
|
||||
const APIlogger = (req, res, next) => {
|
||||
try {
|
||||
const log = {
|
||||
ip: req.ip,
|
||||
time: new Date().toUTCString(),
|
||||
method: req.method,
|
||||
//https://stackoverflow.com/questions/10183291/how-to-get-the-full-url-in-express
|
||||
host: `${req.protocol}://${req.get("host")}${req.originalUrl}`,
|
||||
statusCode: res.statusCode,
|
||||
Responsesize: res.get('Content-Length') ? res.get('Content-Length') : 0,
|
||||
referrer: res.get('content-type') ? res.get('content-type') : "none",
|
||||
userAgent: req.headers["user-agent"],
|
||||
};
|
||||
//upload to db logic here for api logs
|
||||
insertLogData(log);
|
||||
next();
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = { APIlogger };
|
||||
|
||||
|
||||
/*
|
||||
method: req.method,
|
||||
statusCode: res.statusCode,
|
||||
protocol: req.protocol,
|
||||
//formatted in nice utc format
|
||||
time: new Date().toUTCString(),
|
||||
ip: req.ip,
|
||||
userAgent: req.headers["user-agent"],
|
||||
host: `${req.protocol}://${req.get("host")}${req.originalUrl}`,
|
||||
*/
|
65
consumerWebsite/mqttApp.js
Normal file
65
consumerWebsite/mqttApp.js
Normal file
@ -0,0 +1,65 @@
|
||||
const client = require("./modules/mqtt");
|
||||
const { isJson, isNumber } = require("./functions/validateData.js");
|
||||
const { addSensorData } = require("./functions/sensors.js");
|
||||
|
||||
// Event handlers
|
||||
client.on("connect", () => {
|
||||
console.log("Connected to MQTT broker");
|
||||
client.subscribe("iot-data");
|
||||
});
|
||||
|
||||
client.on("message", (topic, message) => {
|
||||
try {
|
||||
let datas = JSON.parse(message);
|
||||
if (isJson(datas)) {
|
||||
for (let key in datas) {
|
||||
let data = parseInt(
|
||||
datas[key].locationid +
|
||||
" " +
|
||||
datas[key].sensorid +
|
||||
" " +
|
||||
datas[key].measurement.psi +
|
||||
" " +
|
||||
datas[key].measurement.humidity +
|
||||
" " +
|
||||
datas[key].measurement.o3 +
|
||||
" " +
|
||||
datas[key].measurement.no2 +
|
||||
" " +
|
||||
datas[key].measurement.so2 +
|
||||
" " +
|
||||
datas[key].measurement.co +
|
||||
" " +
|
||||
datas[key].measurement.temperature +
|
||||
" " +
|
||||
datas[key].measurement.windspeed
|
||||
);
|
||||
if (isNumber(data)) {
|
||||
{
|
||||
//pass datas to database
|
||||
insertDatatoDB(datas[key].sensorid, datas[key].locationid, datas[key]);
|
||||
|
||||
}
|
||||
} else {
|
||||
console.log("Invalid data");
|
||||
client.end();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log("Invalid data");
|
||||
client.end();
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
|
||||
client.on("error", (err) => {
|
||||
console.error("Error:", err);
|
||||
client.end();
|
||||
});
|
||||
|
||||
client.on("end", () => {
|
||||
console.log("Disconnected from MQTT broker");
|
||||
client.reconnect();
|
||||
});
|
@ -1,13 +1,22 @@
|
||||
'use strict';
|
||||
const router = require('express').Router();
|
||||
const { auth } = require("../middleware/authChecker")
|
||||
|
||||
const { auth } = require("../middleware/authChecker")
|
||||
const { APIlogger } = require('../middleware/apiLogger.js');
|
||||
|
||||
router.use('/auth', require('./auth'));
|
||||
|
||||
router.use('/apikey', require('./apikey'));
|
||||
|
||||
router.use('/user', auth ,require('./user'));
|
||||
router.use('/user', [auth, APIlogger], require('./user'));
|
||||
|
||||
//location route
|
||||
router.use('/location', [auth, APIlogger], require('./location'));
|
||||
|
||||
//location route
|
||||
router.use('/sensor', [auth, APIlogger], require('./sensor'));
|
||||
|
||||
//location route
|
||||
router.use('/sensor-data', [auth, APIlogger], require('./sensorData'));
|
||||
|
||||
module.exports = router;
|
||||
|
||||
|
76
consumerWebsite/routes/location.js
Normal file
76
consumerWebsite/routes/location.js
Normal file
@ -0,0 +1,76 @@
|
||||
const {
|
||||
addLocation,
|
||||
getLocation,
|
||||
getLocationById,
|
||||
updateLocation,
|
||||
deleteLocation,
|
||||
} = require("../functions/location");
|
||||
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
|
||||
//get location
|
||||
router.get("/", async (req, res, next) => {
|
||||
try {
|
||||
const location = await getLocation();
|
||||
//res send json and status code
|
||||
res.status(200).json(location);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//add location
|
||||
router.post("/new", async (req, res, next) => {
|
||||
try {
|
||||
const { name, added_by, description } = req.body;
|
||||
await addLocation(name, added_by, description);
|
||||
res.sendStatus(200)
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
//update location
|
||||
router.put("/update", async (req, res, next) => {
|
||||
try {
|
||||
const { id, name, added_by, description } = req.body;
|
||||
await updateLocation(id, name, added_by, description);
|
||||
res.status(200).json({ message: "Location " + id + " updated" });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
//delete location
|
||||
router.delete("/delete", async (req, res, next) => {
|
||||
try {
|
||||
const { id } = req.body;
|
||||
await deleteLocation(id);
|
||||
res.status(200).json({ message: "Location " + id + " deleted" });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
//get location by id
|
||||
router.get("/:id", async (req, res, next) => {
|
||||
try {
|
||||
//get params
|
||||
const { id } = req.params;
|
||||
const location = await getLocationById(id);
|
||||
res.status(200).json(location);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
41
consumerWebsite/routes/seedLocationAndSensor.js
Normal file
41
consumerWebsite/routes/seedLocationAndSensor.js
Normal file
@ -0,0 +1,41 @@
|
||||
const { sequelize } = require("../database/mySql.js");
|
||||
const { locationModel } = require("../database/model/locationModel.js");
|
||||
const { sensorModel } = require("../database/model/sensorModel.js");
|
||||
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
|
||||
let mockLocation = []
|
||||
|
||||
//add seed
|
||||
router.post("/new", async (req, res, next) => {
|
||||
try {
|
||||
console.log(mockLocation)
|
||||
|
||||
for(let locationName of req.body.mockLocation){
|
||||
//create location and create sensor
|
||||
let location = await locationModel.create({
|
||||
name: locationName,
|
||||
added_by: "system",
|
||||
description: "system generated location",
|
||||
});
|
||||
await sensorModel.create({
|
||||
name: `AQI-${Math.floor(Math.random()*898)+101}`,
|
||||
added_by: "system",
|
||||
mac_address: `${Math.floor(Math.random()*256).toString(16).padStart(2, '0')}-${Math.floor(Math.random()*256).toString(16).padStart(2, '0')}-${Math.floor(Math.random()*256).toString(16).padStart(2, '0')}-${Math.floor(Math.random()*256).toString(16).padStart(2, '0')}-${Math.floor(Math.random()*256).toString(16).padStart(2, '0')}-${Math.floor(Math.random()*256).toString(16).padStart(2, '0')}`,
|
||||
description: "system generated sensor",
|
||||
locationid: location.id
|
||||
|
||||
});
|
||||
}
|
||||
res.sendStatus(200)
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
module.exports = router;
|
122
consumerWebsite/routes/seedSensorData.js
Normal file
122
consumerWebsite/routes/seedSensorData.js
Normal file
@ -0,0 +1,122 @@
|
||||
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 express = require("express");
|
||||
const router = express.Router();
|
||||
var moment = require("moment");
|
||||
|
||||
async function seedSensorData(seedOptions) {
|
||||
seedOptions.endDate = new Date(seedOptions.endDate) || Date.now();
|
||||
seedOptions.interval = seedOptions.interval || 15; //15 minutes
|
||||
seedOptions.sensorid = seedOptions.sensorid || (await sensorModel.findAll()).map((i) => i.id);
|
||||
seedOptions.seedData = seedOptions.seedData || {};
|
||||
|
||||
let rows = [];
|
||||
|
||||
for (let sensorId of seedOptions.sensorid) {
|
||||
let sensor = await sensorModel.findByPk(sensorId);
|
||||
let locationId = sensor.locationid;
|
||||
|
||||
let currentRow = firstDataRow(seedOptions.startDate, sensorId, locationId);
|
||||
rows.push(currentRow);
|
||||
while (currentRow.createdAt <= seedOptions.endDate) {
|
||||
currentRow = nextDataRow(currentRow, seedOptions.interval);
|
||||
rows.push(currentRow);
|
||||
}
|
||||
}
|
||||
|
||||
await sensorDataModel.bulkCreate(rows)
|
||||
}
|
||||
|
||||
function convertDateToUTC(startDate) {
|
||||
let date = new Date(startDate);
|
||||
date = moment(date).utc().toDate();
|
||||
//return as object
|
||||
return date;
|
||||
}
|
||||
|
||||
//populate first row of sensordata model with random data from seedData
|
||||
function firstDataRow(startDate, sensorId, locationId) {
|
||||
return {
|
||||
sensorid: sensorId,
|
||||
locationid: locationId,
|
||||
measurement: {
|
||||
psi: Math.floor(Math.random() * 30) + 5,
|
||||
humidity: Math.floor(Math.random() * (90 - 80 + 1) + 80),
|
||||
o3: Math.floor(Math.random() * (100 - 20 + 1) + 30),
|
||||
no2: Math.floor(Math.random() * 30) + 5,
|
||||
so2: Math.floor(Math.random() * 30) + 5,
|
||||
co: Math.floor(Math.random() * 25 - 0.5),
|
||||
temperature: Math.floor(Math.random() * (30 - 23 + 1) + 25),
|
||||
windspeed: Math.floor(Math.random() * (10 - 1 + 1) + 1),
|
||||
},
|
||||
createdAt: convertDateToUTC(startDate),
|
||||
};
|
||||
}
|
||||
|
||||
function nextDataRow(currentRow, interval) {
|
||||
return {
|
||||
sensorid: currentRow.sensorid,
|
||||
locationid: currentRow.locationid,
|
||||
measurement: {
|
||||
psi: numberWithinPercent(currentRow.measurement.psi),
|
||||
humidity: Math.floor(Math.random() * (90 - 80 + 1) + 80),
|
||||
o3: numberWithinPercent(currentRow.measurement.o3),
|
||||
no2: numberWithinPercent(currentRow.measurement.no2),
|
||||
so2: numberWithinPercent(currentRow.measurement.so2),
|
||||
co: numberWithinPercent(currentRow.measurement.co),
|
||||
temperature: Math.floor(Math.random() * (30 - 23 + 1) + 25),
|
||||
windspeed: Math.floor(Math.random() * (10 - 1 + 1) + 1),
|
||||
},
|
||||
//add 15 minutes to current row time to get next row time in UTC
|
||||
createdAt: moment(currentRow.createdAt).add(interval, "m").toDate(),
|
||||
};
|
||||
}
|
||||
|
||||
function numberWithinPercent(inputNumber) {
|
||||
// Define a reasonable range for the random offset
|
||||
const maxOffset = 5;
|
||||
const minOffset = -5;
|
||||
|
||||
// Add a random offset within the defined range
|
||||
const randomOffset = Math.random() * (maxOffset - minOffset) + minOffset;
|
||||
|
||||
// Calculate the new number with the offset
|
||||
const newNumber = inputNumber + randomOffset;
|
||||
|
||||
// Ensure the new number is within a reasonable range
|
||||
return Math.max(5, Math.min(100, Math.floor(newNumber)));
|
||||
}
|
||||
|
||||
//add seed
|
||||
router.post("/new", async (req, res, next) => {
|
||||
try {
|
||||
const seedOptions = req.body;
|
||||
console.log(seedOptions);
|
||||
seedSensorData(seedOptions);
|
||||
res.status(200)
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
/*
|
||||
POST /api/v0/seed/sensordata
|
||||
{
|
||||
"startDate" : "10-10-2010", // Date to start faking data REQUIRED
|
||||
"endDate": "10-10-2011", // Date to stop fake data, optional defaults today
|
||||
"interval": 150000, // Time in seconds between sensor polling
|
||||
"sensors": [0,1,2], // ID of sensors to fake, optional defaults to all
|
||||
"seedData": {"object of sensor data"} // The first sensor data row to start with, optional, will use random function as default
|
||||
}
|
||||
|
||||
1) firstDataRow(startDate)
|
||||
2) nextDataRow(lastRow, interval)
|
||||
3) seedSensorData({post object from abovr})
|
||||
|
||||
*/
|
14
consumerWebsite/routes/seed_route.js
Normal file
14
consumerWebsite/routes/seed_route.js
Normal file
@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
const router = require('express').Router();
|
||||
|
||||
//location route
|
||||
router.use('/sensor-data', require('./seedSensorData.js'));
|
||||
|
||||
router.use('/seed', require('./seedLocationAndSensor'));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
module.exports = router;
|
66
consumerWebsite/routes/sensor.js
Normal file
66
consumerWebsite/routes/sensor.js
Normal file
@ -0,0 +1,66 @@
|
||||
const {
|
||||
getSensor,
|
||||
addSensor,
|
||||
updateSensor,
|
||||
deleteSensor,
|
||||
getSensorById
|
||||
} = require("../functions/sensor.js");
|
||||
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/", async (req, res, next) => {
|
||||
try {
|
||||
const sensor = await getSensor();
|
||||
res.status(200).json(sensor);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
router.post("/new", async (req, res, next) => {
|
||||
try {
|
||||
const { sensorname, added_by, mac_address , description, location } = req.body;
|
||||
await addSensor(sensorname, added_by, mac_address ,description, location);
|
||||
res.sendStatus(200)
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
router.put("/update", async (req, res, next) => {
|
||||
try {
|
||||
const { id, sensorname, added_by, mac_address ,description, location } = req.body;
|
||||
await updateSensor(id, sensorname, added_by, mac_address , description, location);
|
||||
res.status(200).json({ message: "Sensor " + id + " updated" });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
router.delete("/delete", async (req, res, next) => {
|
||||
try {
|
||||
const { id } = req.body;
|
||||
await deleteSensor(id);
|
||||
res.status(200).json({ message: "Sensor " + id + " deleted" });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
router.get("/:id", async (req, res, next) => {
|
||||
try {
|
||||
const sensor = await getSensorById(req.params.id);
|
||||
res.status(200).json(sensor);
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
94
consumerWebsite/routes/sensorData.js
Normal file
94
consumerWebsite/routes/sensorData.js
Normal file
@ -0,0 +1,94 @@
|
||||
const {
|
||||
getSensorData,
|
||||
addSensorData,
|
||||
updateSensorData,
|
||||
deleteSensorData,
|
||||
getSensorDataById,
|
||||
getData,
|
||||
getDatabyRange,
|
||||
} = require("../functions/sensorData");
|
||||
|
||||
const express = require("express");
|
||||
const { json } = require("body-parser");
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/", async (req, res, next) => {
|
||||
try {
|
||||
const sensor = await getSensorData();
|
||||
res.status(200).json(sensor);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
router.post("/new", async (req, res, next) => {
|
||||
try {
|
||||
const { id_sensor, id_location, sensordata } = req.body;
|
||||
await addSensorData(id_sensor, id_location, sensordata);
|
||||
res.sendStatus(200).json({ message: "SensorData " + id + " added" });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
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" });
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
router.get("/data", async (req, res, next) => {
|
||||
try {
|
||||
console.log(req.query);
|
||||
const data = await getData(req.query);
|
||||
res.status(200).json(data);
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
//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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
@ -24,7 +24,7 @@
|
||||
<div class="error-contents">
|
||||
<h3>Unauthorized Access!</h3>
|
||||
<div class="error-img">
|
||||
<img class="img-fluid" src="images/401.png" alt="" />
|
||||
<img class="img-fluid" src="/images/401.png" alt="" />
|
||||
</div>
|
||||
<p>Sorry, you don't have permission to access this resource. Please log in or provide valid credentials.</p>
|
||||
<a class="btn btn-primary" href="/"> Back To Homepage </a>
|
||||
|
@ -24,7 +24,7 @@
|
||||
<div class="error-contents">
|
||||
<h3>Oops! That page can’t be found.</h3>
|
||||
<div class="error-img">
|
||||
<img class="img-fluid" src="images/404.png" alt="" />
|
||||
<img class="img-fluid" src="/images/404.png" alt="" />
|
||||
</div>
|
||||
<p>We can’t find the page your are looking for. You can check out our <a href="/">Homepage</a>.</p>
|
||||
<a class="btn btn-primary" href="/"> Back To Homepage </a>
|
||||
|
@ -45,7 +45,7 @@
|
||||
<ul class="footer_ul_amrc">
|
||||
<li class="media">
|
||||
<div class="media-left">
|
||||
<img class="img-fluid" src="images/post-img-01.jpg" alt="" />
|
||||
<img class="img-fluid" src="/images/post-img-01.jpg" alt="" />
|
||||
</div>
|
||||
<div class="media-body">
|
||||
<p>Singapore's air quality ...</p>
|
||||
@ -55,7 +55,7 @@
|
||||
<ul class="footer_ul_amrc">
|
||||
<li class="media">
|
||||
<div class="media-left">
|
||||
<img class="img-fluid" src="images/post-img-01.jpg" alt="" />
|
||||
<img class="img-fluid" src="/images/post-img-01.jpg" alt="" />
|
||||
</div>
|
||||
<div class="media-body">
|
||||
<p>Singapore Government ...</p>
|
||||
@ -65,7 +65,7 @@
|
||||
<ul class="footer_ul_amrc">
|
||||
<li class="media">
|
||||
<div class="media-left">
|
||||
<img class="img-fluid" src="images/post-img-01.jpg" alt="" />
|
||||
<img class="img-fluid" src="/images/post-img-01.jpg" alt="" />
|
||||
</div>
|
||||
<div class="media-body">
|
||||
<p>High risk of severe ...</p>
|
||||
@ -81,7 +81,7 @@
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
<script src="js/search.js"></script>
|
||||
<script src="/js/search.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -6,7 +6,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<link rel="shortcut icon" type="images/logo.ico" href="images/logo.ico" />
|
||||
<link rel="shortcut icon" type="images/logo.ico" href="/images/logo.ico" />
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
||||
|
@ -9,7 +9,7 @@
|
||||
<meta http-equiv="cleartype" content="on" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="shortcut icon" type="images/logo.ico" href="images/logo.ico" />
|
||||
<link rel="shortcut icon" type="/images/logo.ico" href="/images/logo.ico" />
|
||||
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
@ -17,8 +17,8 @@
|
||||
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous" />
|
||||
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="css/all.css" rel="stylesheet" />
|
||||
<link href="css/style.css" rel="stylesheet" />
|
||||
<link href="/css/all.css" rel="stylesheet" />
|
||||
<link href="/css/style.css" rel="stylesheet" />
|
||||
<!-- weird api page cdn -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
@ -45,10 +45,10 @@
|
||||
|
||||
|
||||
<!-- jq-repeat -->
|
||||
<script src="js/jq-repeat.js"></script>
|
||||
<script src="/js/jq-repeat.js"></script>
|
||||
|
||||
<!-- jquery app.js -->
|
||||
<script src="js/app.js"></script>
|
||||
<script src="/js/app.js"></script>
|
||||
</head>
|
||||
<!-- javascript function to check if user is auth -->
|
||||
<script>
|
||||
@ -74,7 +74,7 @@
|
||||
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="/">
|
||||
<img src="images/logo.png" alt="logo" />
|
||||
<img src="/images/logo.png" alt="logo" />
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive"
|
||||
aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
|
||||
|
Reference in New Issue
Block a user