Merge branch 'main' of https://github.com/Newtbot/MP
This commit is contained in:
@ -50,49 +50,48 @@ app.use("/", require("./routes/render"));
|
||||
// Catch 404 and forward to error handler. If none of the above routes are
|
||||
// used, this is what will be called.
|
||||
app.use(function (req, res, next) {
|
||||
//application/json; charset=utf-8
|
||||
if (req.is("application/json" || "application/json; charset=utf-8")) {
|
||||
var err = new Error("Not Found");
|
||||
err.message = "Page not found";
|
||||
err.status = 404;
|
||||
next(err);
|
||||
} else {
|
||||
res.status(404).render("404");
|
||||
}
|
||||
//application/json; charset=utf-8
|
||||
var err = new Error("Not Found");
|
||||
err.message = "Page not found";
|
||||
err.status = 404;
|
||||
next(err);
|
||||
});
|
||||
|
||||
// Error handler. This is where `next()` will go on error
|
||||
app.use(function (err, req, res, next) {
|
||||
console.error(err.status || res.status, err.name, req.method, req.url);
|
||||
if (![404].includes(err.status || res.status)) {
|
||||
console.error(err.message);
|
||||
console.error(err.stack);
|
||||
console.error("=========================================");
|
||||
}
|
||||
console.error(err.status || res.status, err.name, req.method, req.url);
|
||||
|
||||
console.log(err.name + " validation error");
|
||||
// Parse key error for Sequilzw
|
||||
let keyErrors = {};
|
||||
if (["SequelizeValidationError"].includes(err.name) && err.errors) {
|
||||
for (let item of err.errors) {
|
||||
if (item.path) {
|
||||
keyErrors[item.path] = item.message;
|
||||
}
|
||||
}
|
||||
res.status = 422;
|
||||
}
|
||||
// Parse key error for Sequilzw
|
||||
let keyErrors = {};
|
||||
if (["SequelizeValidationError"].includes(err.name) && err.errors) {
|
||||
for (let item of err.errors) {
|
||||
if (item.path) {
|
||||
keyErrors[item.path] = item.message;
|
||||
}
|
||||
}
|
||||
res.status = 422;
|
||||
}
|
||||
|
||||
if (![404, 422].includes(err.status || res.status)) {
|
||||
console.error(err.message);
|
||||
console.error(err.stack);
|
||||
console.error("=========================================");
|
||||
}
|
||||
if (![404, 401, 422].includes(err.status || res.status)) {
|
||||
console.error(err.message);
|
||||
console.error(err.stack);
|
||||
console.error("=========================================");
|
||||
}
|
||||
res.status(err.status || 500);
|
||||
// res.status(err.status || 500);
|
||||
|
||||
|
||||
res.status(err.status || 500);
|
||||
res.json({
|
||||
name: err.name || "Unknown error",
|
||||
message: err.message,
|
||||
keyErrors,
|
||||
});
|
||||
});
|
||||
if (req.get('Content-Type') && req.get('Content-Type').includes("json")) {
|
||||
res.json({
|
||||
name: err.name || "Unknown error",
|
||||
message: err.message,
|
||||
keyErrors,
|
||||
});
|
||||
}
|
||||
else {
|
||||
res.json({
|
||||
name: err.name || "Unknown error",
|
||||
message: err.message,
|
||||
keyErrors,
|
||||
});
|
||||
}
|
||||
});
|
@ -107,4 +107,6 @@ const sensorModel = sequelize.define(
|
||||
}
|
||||
);
|
||||
|
||||
sensorModel.belongsTo(locationModel);
|
||||
|
||||
module.exports = { sensorModel };
|
||||
|
@ -3,7 +3,7 @@ const { Sequelize, DataTypes } = require("sequelize");
|
||||
const { sequelize } = require("../mySQL");
|
||||
const { userModel } = require("./userModel");
|
||||
|
||||
//sequelize.sync();
|
||||
sequelize.sync();
|
||||
const tokenModel = sequelize.define(
|
||||
"token",
|
||||
{
|
||||
|
@ -9,13 +9,13 @@ const sequelize = new Sequelize(
|
||||
process.env.DB_USER,
|
||||
process.env.DB_PASS,
|
||||
{
|
||||
host: "mpsqldatabase.mysql.database.azure.com",
|
||||
host: "mpsqldatabasean.mysql.database.azure.com",
|
||||
dialect: 'mysql',
|
||||
// attributeBehavior?: 'escape' | 'throw' | 'unsafe-legacy';
|
||||
attributeBehavior: 'escape',
|
||||
dialectOptions: {
|
||||
ssl: {
|
||||
ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt.pem')),
|
||||
ca: fs.readFileSync(path.resolve(__dirname, '../cert/DigiCertGlobalRootCA.crt_3.pem')),
|
||||
},
|
||||
|
||||
},
|
||||
|
@ -1,19 +1,41 @@
|
||||
const { hash, compareHash } = require("./bcrypt.js");
|
||||
const { tokenModel } = require("../database/model/tokenModel.js");
|
||||
const { userModel } = require("../database/model/userModel");
|
||||
const { hash, compareHash } = require("./bcrypt.js");
|
||||
const { generateUUID } = require("./generateUUID.js");
|
||||
const { isValid } = require("./isValid");
|
||||
|
||||
/*
|
||||
1) take userid
|
||||
2) generate random api key
|
||||
3) hash the api key
|
||||
4) append userid with - and api key
|
||||
5) you give the user rowid-uuidv4
|
||||
6) store in database
|
||||
*/
|
||||
//can be used for api key or token. Both are the same logic
|
||||
async function addToken(userId, permission , expiry) {
|
||||
async function getTokenByToken(token) {
|
||||
const splitAuthToken = token.split("-");
|
||||
const rowid = splitAuthToken[0];
|
||||
const suppliedToken = splitAuthToken.slice(1).join("-");
|
||||
|
||||
token = await tokenModel.findByPk(rowid, { include: userModel });
|
||||
|
||||
token.isValid = await compareHash(suppliedToken, token.token); //true
|
||||
console.log("function api getTokenByToken token", token.isValid);
|
||||
token.isValid = token.isValid && isValid(token.expiration);
|
||||
console.log("function api getTokenByToken token", token.isValid);
|
||||
if (!token.isValid) {
|
||||
//add boolean to token table
|
||||
token.destroy();
|
||||
}
|
||||
/*
|
||||
console.log(
|
||||
"function api getTokenByToken token",
|
||||
await compareHash(suppliedToken, token.token),
|
||||
isValid("token" , token.expiration)
|
||||
);
|
||||
*/
|
||||
console.log(token.isValid);
|
||||
return token;
|
||||
}
|
||||
|
||||
async function addToken(userId, permission, expiry) {
|
||||
let uuid = await generateUUID();
|
||||
let hashtoken = await hash(uuid);
|
||||
//console.log("user id", userId);
|
||||
// return { token: token, userid: userRes.id, username: userRes.username };
|
||||
// let token = await addToken(userRes.id , "canRead" , tokenToLive);
|
||||
|
||||
let token = await tokenModel.create({
|
||||
userid: userId,
|
||||
@ -26,23 +48,4 @@ async function addToken(userId, permission , expiry) {
|
||||
return token.id + "-" + uuid;
|
||||
}
|
||||
|
||||
async function checkToken(Supplied, rowid) {
|
||||
try {
|
||||
const retrivedToken = await tokenModel.findOne({
|
||||
raw: true,
|
||||
attributes: ["token", "permission"],
|
||||
where: {
|
||||
id: rowid,
|
||||
},
|
||||
});
|
||||
//console.log(retrivedKey.apikey);
|
||||
if (compareHash(Supplied, retrivedToken.token)) {
|
||||
//return true;
|
||||
return retrivedToken.permission;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { addToken , checkToken };
|
||||
module.exports = { addToken, getTokenByToken };
|
||||
|
@ -1,20 +1,14 @@
|
||||
const moment = require("moment");
|
||||
const currentTime = moment().format("YYYY-MM-DD HH:mm:ss");
|
||||
|
||||
//time is taken from the token
|
||||
function isValid(time){
|
||||
const timeDiff = moment(currentTime).diff(time, "minutes");
|
||||
|
||||
if (timeDiff > 1) {
|
||||
console.log(timeDiff);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
function isValid(time) {
|
||||
|
||||
if (
|
||||
Math.floor(new Date(time).getTime() / 1000) <
|
||||
Math.floor(new Date().getTime() / 1000)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
module.exports = { isValid };
|
||||
module.exports = { isValid };
|
||||
|
82
consumerWebsite/functions/nodeMail.js
Normal file
82
consumerWebsite/functions/nodeMail.js
Normal file
@ -0,0 +1,82 @@
|
||||
const { transporter } = require("../modules/nodemailer");
|
||||
const path = require("path");
|
||||
require("dotenv").config({ path: path.resolve(__dirname, "../.env") });
|
||||
|
||||
/*
|
||||
var message = {
|
||||
from: "sender@server.com",
|
||||
to: "receiver@sender.com",
|
||||
subject: "Message title",
|
||||
text: "Plaintext version of the message",
|
||||
html: "<p>HTML version of the message</p>",
|
||||
};
|
||||
//send mail with defined transport object
|
||||
transporter.sendMail(data[, callback])
|
||||
|
||||
*/
|
||||
|
||||
async function sendContactEmail(email, name, message) {
|
||||
console.log(email, name, message);
|
||||
|
||||
try {
|
||||
let contactMessage = await transporter.sendMail({
|
||||
to: process.env.euser,
|
||||
subject: "Contact us Message",
|
||||
html: `
|
||||
<h1>Contact us Message</h1>
|
||||
<p><strong>From:</strong> ${name}</p>
|
||||
<p><strong>User Email:</strong> ${email}</p>
|
||||
<p><strong>Message:</strong> ${message}</p>
|
||||
<p>Thank you for contacting us. We will get back to you as soon as possible.</p>
|
||||
<p>Regards,</p>
|
||||
<p>EcoSaver Team</p>
|
||||
<p><a href="https://ecosaver.teeseng.uk/">EcoSaver Website</a></p>
|
||||
<p>Please do not reply to this email.</p>
|
||||
`,
|
||||
});
|
||||
transporter.sendMail({ contactMessage }, function (error, info) {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
} else {
|
||||
console.log("Email sent: " + info.response);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function sendTokenEmail(email, token) {
|
||||
|
||||
try {
|
||||
let tokenMessage = await transporter.sendMail({
|
||||
to: email,
|
||||
from: process.env.euser,
|
||||
subject: "API Token",
|
||||
html: `
|
||||
<h1>API Token</h1>
|
||||
<p><strong>Token:</strong> ${token}</p>
|
||||
<p>Please do not lose this token and do not share your token with anyone!</p>
|
||||
<p>Thank you for using EcoSaver.</p>
|
||||
<p>Regards,</p>
|
||||
<p>EcoSaver Team</p>
|
||||
<p><a href="https://ecosaver.teeseng.uk/">EcoSaver Website</a></p>
|
||||
<p>Please do not reply to this email.</p>
|
||||
|
||||
`,
|
||||
});
|
||||
transporter.sendMail({ tokenMessage }, function (error, info) {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
} else {
|
||||
console.log("Email sent: " + info.response);
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = { sendContactEmail , sendTokenEmail };
|
@ -18,15 +18,17 @@ 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,
|
||||
locationid: id_location ,
|
||||
measurement: sensordata.measurement,
|
||||
});
|
||||
io().emit('sensorData:new', sensorData)
|
||||
//console.log("sensorData", sensorData);
|
||||
//console.log("sensorData", sensordata.measurement);
|
||||
|
||||
|
||||
io().emit('sensorData:new', sensordata)
|
||||
return sensorData;
|
||||
}
|
||||
|
||||
@ -61,6 +63,14 @@ async function getSensorDataById(id) {
|
||||
});
|
||||
return sensorData;
|
||||
}
|
||||
|
||||
async function getLatestData() {
|
||||
const sensorData = await sensorDataModel.findAll({
|
||||
limit: 6,
|
||||
order: [["createdAt", "DESC"]],
|
||||
});
|
||||
return sensorData;
|
||||
}
|
||||
var ormQuery = {};
|
||||
var whereClause = {};
|
||||
var whereDate = {};
|
||||
@ -724,5 +734,6 @@ module.exports = {
|
||||
getSensorDataById,
|
||||
getData,
|
||||
getDatabyRange,
|
||||
getLatestData,
|
||||
|
||||
};
|
@ -2,7 +2,6 @@ const { Op } = require('sequelize')
|
||||
const { hash, compareHash } = require("./bcrypt.js");
|
||||
const { addToken } = require("./api");
|
||||
const { userModel } = require("../database/model/userModel");
|
||||
moment = require('moment')
|
||||
|
||||
|
||||
|
||||
@ -21,6 +20,16 @@ async function getUserByID(userid) {
|
||||
return userRes;
|
||||
}
|
||||
|
||||
async function getUserByEmail(email) {
|
||||
let userRes = await userModel.findOne({
|
||||
where: {
|
||||
email: email,
|
||||
},
|
||||
});
|
||||
if (!userRes) return false;
|
||||
return userRes;
|
||||
}
|
||||
|
||||
//api/v0/auth/register
|
||||
/* Registering new user
|
||||
1) req.body is taken from html form or wtv
|
||||
@ -71,9 +80,11 @@ async function loginUser(user) {
|
||||
if (!match) return false;
|
||||
//console.log('loginUser', userRes.id, userRes.username);
|
||||
|
||||
//generate token and permission and experiation time
|
||||
const currentTime = moment().format('YYYY-MM-DD HH:mm:ss');
|
||||
let token = await addToken(userRes.id , "canRead" , currentTime);
|
||||
//generate token and permission and experiation time + 30 mins
|
||||
//let tokenToLive = moment().add(30, 'minutes').format();
|
||||
let currentDate = new Date();
|
||||
let tokenToLive = new Date(currentDate.getTime() + 30 * 60000);
|
||||
let token = await addToken(userRes.id , "canRead" , tokenToLive);
|
||||
return { token: token, userid: userRes.id, username: userRes.username };
|
||||
}
|
||||
|
||||
@ -130,9 +141,23 @@ async function updateProfile(user, body) {
|
||||
}
|
||||
}
|
||||
|
||||
async function checkEmail(email) {
|
||||
let emailRes = await userModel.findOne({
|
||||
where: {
|
||||
email: email,
|
||||
},
|
||||
});
|
||||
if (!emailRes) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
getUserByID,
|
||||
getUserByEmail,
|
||||
addUser,
|
||||
loginUser,
|
||||
updateProfile,
|
||||
checkEmail
|
||||
};
|
@ -1,68 +1,48 @@
|
||||
const { tokenModel } = require("../database/model/tokenModel");
|
||||
const { userModel } = require("../database/model/userModel");
|
||||
const { compareHash } = require("../functions/bcrypt");
|
||||
const { checkToken } = require("../functions/api");
|
||||
const { isValid } = require("../functions/isValid");
|
||||
const { getTokenByToken } = require("../functions/api");
|
||||
|
||||
const permissionError = new Error('PermissionError')
|
||||
permissionError.name = "Inadequate Permission Error"
|
||||
permissionError.status = 401
|
||||
permissionError.message = "Inadequate permission to complete this response"
|
||||
|
||||
async function auth(req, res, next) {
|
||||
try {
|
||||
const authToken = req.header("auth-token");
|
||||
if (!authToken) {
|
||||
const error = new Error("No Token key was supplied. Invalid request");
|
||||
throw error;
|
||||
const token = await getTokenByToken(req.header("auth-token"));
|
||||
|
||||
if (!token || !token.isValid){
|
||||
throw permissionError;
|
||||
}
|
||||
|
||||
const splitAuthToken = authToken.split("-");
|
||||
const rowid = splitAuthToken[0];
|
||||
const suppliedToken = splitAuthToken.slice(1).join("-");
|
||||
|
||||
const token = await tokenModel.findByPk(rowid, { include: userModel });
|
||||
|
||||
if (!token) {
|
||||
const error = new Error("Token key not found. Invalid request");
|
||||
throw error;
|
||||
}
|
||||
|
||||
const isMatch = await compareHash(suppliedToken, token.token);
|
||||
|
||||
console.log(isMatch);
|
||||
if (!isMatch) {
|
||||
const error = new Error("Token key not found. Invalid request");
|
||||
throw error;
|
||||
}
|
||||
//if token is a match
|
||||
req.token = token;
|
||||
req.user = await token.getUser();
|
||||
const permission = await checkToken(suppliedToken, rowid);
|
||||
|
||||
const route = req.originalUrl.split("?")[0]; // Removing query parameters
|
||||
//if route is from user/ and permission is canRead allow it to do CRUD
|
||||
if (route.includes("/user/") && permission === "canRead") {
|
||||
next();
|
||||
if (route.includes("/user/") || route.includes("/token/") && token.permission === "canRead") {
|
||||
console.log("user route");
|
||||
return next();
|
||||
}
|
||||
if ((req.method === "GET" && permission === "canRead") || (["GET", "POST", "PUT", "DELETE"].includes(req.method) && permission === "canWrite")) {
|
||||
next();
|
||||
}
|
||||
|
||||
if (!isValid(token.expiration)){
|
||||
req.token.destroy();
|
||||
throw new Error("Token expired");
|
||||
if ((req.method === "GET" && token.permission === "canRead")){
|
||||
console.log("wtf you shldnt be here");
|
||||
return next();
|
||||
}
|
||||
if (["GET", "POST", "PUT", "DELETE"].includes(req.method) && token.permission === "canWrite") {
|
||||
console.log("wtf you shldnt be here");
|
||||
return next();
|
||||
}
|
||||
/*
|
||||
if ((req.method === "GET" && token.permission === "canRead") ||
|
||||
(["GET", "POST", "PUT", "DELETE"].includes(req.method) && token.permission === "canWrite")) {
|
||||
return next();
|
||||
}
|
||||
*/
|
||||
|
||||
throw permissionError
|
||||
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { auth };
|
||||
|
||||
/*
|
||||
else {
|
||||
const error = new Error("Insufficient permission");
|
||||
error.status = 401;
|
||||
throw error;
|
||||
}
|
||||
|
||||
*/
|
@ -2,6 +2,7 @@ const nodemailer = require("nodemailer");
|
||||
const dotenv = require("dotenv");
|
||||
const path = require('path')
|
||||
require('dotenv').config({ path: path.resolve(__dirname, '../.env') })
|
||||
//.env
|
||||
|
||||
let transporter = nodemailer.createTransport({
|
||||
service: 'gmail',
|
||||
|
@ -3812,6 +3812,7 @@
|
||||
|
||||
.card-text {
|
||||
color: #000000;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* edit profile */
|
||||
|
@ -528,23 +528,22 @@ body.one-content-column-version .content thead {
|
||||
|
||||
|
||||
.generate-key-button {
|
||||
float: right; /* Align the button to the right */
|
||||
margin-right: 85%;
|
||||
margin-top: -40px; /* Adjust the margin-top value based on your layout */
|
||||
/* Add any additional styling you want for the button */
|
||||
}
|
||||
|
||||
#content-get-api .generate-key-button {
|
||||
margin-top: -40px;
|
||||
margin-left: 25px;
|
||||
background-color: #4caf50; /* Green background color */
|
||||
color: white; /* White text color */
|
||||
color: #ffffff;
|
||||
padding: 5px 11px; /* Padding for the button */
|
||||
border: none; /* Remove button border */
|
||||
border-radius: 5px; /* Add border-radius for rounded corners */
|
||||
cursor: pointer; /* Add pointer cursor on hover */
|
||||
font-size: 14px; /* Font size */
|
||||
}
|
||||
.api-form {
|
||||
margin-top: 20px;
|
||||
margin-left: 25px;
|
||||
}
|
||||
|
||||
#content-get-api .generate-key-button:hover {
|
||||
.generate-key-button:hover {
|
||||
background-color: #45a049; /* Darker green on hover */
|
||||
}
|
||||
|
||||
|
@ -186,9 +186,7 @@ app.auth = (function (app) {
|
||||
function isLoggedIn(callback) {
|
||||
|
||||
if (getToken()) {
|
||||
console.log("you shldnt appear at all");
|
||||
return app.api.get("user/me", function (error, data) {
|
||||
console.log(error, data);
|
||||
if (!error) app.auth.user = data;
|
||||
return callback(error, data);
|
||||
});
|
||||
@ -287,7 +285,7 @@ function formAJAX(btn, del) {
|
||||
//console.log('Data being sent to', $form.attr('action'), formData)
|
||||
|
||||
app.api[method]($form.attr("action"), formData, function (error, data) {
|
||||
//console.log('Data back from the server', error, data)
|
||||
console.log('Data back from the server', error, data)
|
||||
app.util.actionMessage(data.message, $form, error ? "danger" : "success"); //re-populate table
|
||||
if (!error) {
|
||||
$form.trigger("reset");
|
||||
|
@ -18,5 +18,8 @@ router.use('/sensor', [auth, APIlogger], require('./sensor.js'));
|
||||
//sensor data route
|
||||
router.use('/sensor-data', [auth, APIlogger], require('./sensorData.js'));
|
||||
|
||||
//latest sensor data to display on dashboard
|
||||
router.use('/latest-sensor-data', [APIlogger], require('./latestsensorData.js'));
|
||||
|
||||
module.exports = router;
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
const { addUser, loginUser } = require("../functions/user");
|
||||
const { addUser, loginUser, checkEmail } = require("../functions/user");
|
||||
const { sendContactEmail } = require("../functions/nodeMail");
|
||||
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
@ -12,12 +13,11 @@ router.post("/register", async (req, res, next) => {
|
||||
error.message = "The user failed to be craated";
|
||||
error.status = 400;
|
||||
return next(error);
|
||||
} else {
|
||||
return res.json({
|
||||
message: "User created successfully",
|
||||
});
|
||||
}
|
||||
else{
|
||||
return res.json({
|
||||
message: "User created successfully",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
@ -29,20 +29,18 @@ router.post("/login", async (req, res, next) => {
|
||||
try {
|
||||
let Res = await loginUser(req.body);
|
||||
if (Res == false) {
|
||||
let error = new Error("User Login Failed");
|
||||
let error = new Error("User Login Failed");
|
||||
error.status = 400;
|
||||
return next(error);
|
||||
} else {
|
||||
//pass res back to form to be set in local storage
|
||||
return res.json({
|
||||
message: "User login successfully",
|
||||
token: Res.token,
|
||||
userid: Res.userid,
|
||||
username: Res.username,
|
||||
});
|
||||
}
|
||||
else{
|
||||
//pass res back to form to be set in local storage
|
||||
return res.json({
|
||||
message: "User login successfully",
|
||||
token: Res.token,
|
||||
userid: Res.userid,
|
||||
username: Res.username,
|
||||
});
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
@ -52,8 +50,26 @@ router.post("/login", async (req, res, next) => {
|
||||
//contact
|
||||
//auth/contact
|
||||
router.post("/contact", async (req, res, next) => {
|
||||
|
||||
try {
|
||||
//console.log(req.body);
|
||||
let Res = await checkEmail(req.body.email);
|
||||
if (!Res) {
|
||||
let error = new Error("Email not found");
|
||||
error.status = 400;
|
||||
return next(error);
|
||||
}
|
||||
else{
|
||||
//console.log(Res);
|
||||
sendContactEmail(req.body.email, req.body.name, req.body.message);
|
||||
return res.json({
|
||||
message: "Email sent successfully",
|
||||
});
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
||||
|
||||
|
21
consumerWebsite/routes/latestsensorData.js
Normal file
21
consumerWebsite/routes/latestsensorData.js
Normal file
@ -0,0 +1,21 @@
|
||||
const {
|
||||
getLatestData,
|
||||
|
||||
} = require("../functions/sensorData");
|
||||
|
||||
const express = require("express");
|
||||
const router = express.Router();
|
||||
|
||||
router.get("/data", async (req, res, next) => {
|
||||
try {
|
||||
console.log(req.query);
|
||||
const data = await getLatestData();
|
||||
res.status(200).json(data);
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
@ -1,4 +1,7 @@
|
||||
const { addToken } = require("../functions/api");
|
||||
const { checkEmail , getUserByEmail } = require("../functions/user");
|
||||
const { sendTokenEmail } = require("../functions/nodeMail");
|
||||
|
||||
|
||||
|
||||
const express = require("express");
|
||||
@ -15,8 +18,29 @@ const router = express.Router();
|
||||
//'{"userid": "5", "permission": "canRead" ,}'
|
||||
router.post("/new", async (req, res, next) => {
|
||||
try {
|
||||
const token = await addToken(req.body.userid, req.body.permission , "2204-01-24 07:34:36" );
|
||||
res.json({token: token});
|
||||
//console.log(req.body);
|
||||
const Res = await checkEmail(req.body.email);
|
||||
if (!Res) {
|
||||
let error = new Error("Email not found");
|
||||
error.status = 400;
|
||||
return next(error);
|
||||
}
|
||||
else
|
||||
{
|
||||
//console.log("email found");
|
||||
let userid = await getUserByEmail(req.body.email);
|
||||
if (!userid) return false;
|
||||
|
||||
const token = await addToken(userid.id, "canRead" , "2204-01-24 07:34:36" );
|
||||
if (!token) return false;
|
||||
sendTokenEmail(req.body.email, token);
|
||||
res.json({
|
||||
message: "Token generated successfully and sent to email",
|
||||
})
|
||||
|
||||
}
|
||||
//const token = await addToken(req.body.userid, "canRead" , "2204-01-24 07:34:36" );
|
||||
//res.json({token: token});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
next(error);
|
||||
|
@ -8,7 +8,7 @@ const router = express.Router();
|
||||
router.get("/me", async function (req, res, next) {
|
||||
try {
|
||||
let user = await getUserByID(req.user);
|
||||
console.log(user);
|
||||
//console.log(user);
|
||||
res.json({
|
||||
user: user,
|
||||
});
|
||||
|
@ -5,8 +5,12 @@
|
||||
https://github.com/ticlekiwi/API-Documentation-HTML-Template
|
||||
!-->
|
||||
|
||||
<%- include('top') %>
|
||||
<link rel="stylesheet" href="css/api.css" media="all">
|
||||
<%- include('top') %>
|
||||
<script type="text/javascript">
|
||||
// Require login to see this page.
|
||||
app.auth.forceLogin()
|
||||
</script>
|
||||
<link rel="stylesheet" href="css/api.css" media="all">
|
||||
|
||||
<body class="one-content-column-version">
|
||||
<div class="left-menu">
|
||||
@ -50,353 +54,633 @@
|
||||
</div>
|
||||
|
||||
|
||||
<div class="content-page">
|
||||
<div class="content">
|
||||
<div class="overflow-hidden content-section" id="content-get-started">
|
||||
<h1>Get started</h1>
|
||||
<p>
|
||||
The following API is provided by the Eco saver developer team. It allows you to get Location and
|
||||
Sensor and Sensor Data from the Eco saver database.
|
||||
</p>
|
||||
<p>
|
||||
To use this API, you need an <strong>API key</strong>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="overflow-hidden content-section" id="content-get-location">
|
||||
<h2>Get all location</h2>
|
||||
<p>
|
||||
To get Location of sensors you need to make a GET call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location</code>
|
||||
<br>
|
||||
<br>
|
||||
Return Response :<br>
|
||||
<code class="higlighted break-word">{"status":"200"}</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>Your API key.</td>
|
||||
<td>(Required) Example: curl https://api.teeseng.uk/api/v0/location -H "Authorization:
|
||||
{provide your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="overflow-hidden content-section" id="content-get-location-by-id">
|
||||
<h2>Get location by ID</h2>
|
||||
<p>
|
||||
To get Location you need to make a GET call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/{id}</code>
|
||||
<br>
|
||||
<br>
|
||||
Return Response :<br>
|
||||
<code class="higlighted break-word">{"status":"200"}</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>(Required) Your API key.</td>
|
||||
<td>Example: curl https://api.teeseng.uk/api/v0/location -H "Authorization: {provide
|
||||
your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="overflow-hidden content-section" id="content-add-location">
|
||||
<h2>Add Location (Only for system or admin API key)</h2>
|
||||
<p>
|
||||
To add an Location you need to make a POST call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/new</code>
|
||||
<br>
|
||||
<br>
|
||||
Example :<br>
|
||||
<code
|
||||
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/new -H "Content-Type: application/json" -X POST -d '{"name": "SAMPLE", "added_by": "system" , "description": "test"}'</code>
|
||||
<br>
|
||||
<br>
|
||||
Return Response :<br>
|
||||
<code class="higlighted break-word">{"status":"200"}</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>Your API key.</td>
|
||||
<td>(Required) Example: curl https://api.teeseng.uk/api/v0/location/new -H
|
||||
"Authorization: {provide your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Location name</td>
|
||||
<td>JSON</td>
|
||||
<td>Location name.</td>
|
||||
<td>(Required) Location name. Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"name":"Location name"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Added by </td>
|
||||
<td>JSON</td>
|
||||
<td>System or Admin</td>
|
||||
<td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"added_by":"system"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>JSON</td>
|
||||
<td>Description of Location</td>
|
||||
<td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"description":"test"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- update -->
|
||||
<div class="overflow-hidden content-section" id="content-update-location-by-id">
|
||||
<h2>Update Location (Only for system or admin API key)</h2>
|
||||
<p>
|
||||
To update an Location you need to make a PUT call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/update</code>
|
||||
<br>
|
||||
<br>
|
||||
Example :<br>
|
||||
<code
|
||||
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/update -H "Content-Type: application/json" -X POST -d '{"id": "7" , "name": "SAMPLE", "added_by": "system" , "description": "test"}'</code>
|
||||
<br>
|
||||
<br>
|
||||
Return Response :<br>
|
||||
<code class="higlighted break-word">{"status":"200","message":"Location 7 updated"}</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>Your API key.</td>
|
||||
<td>(Required) example: curl https://api.teeseng.uk/api/v0/location/update -H
|
||||
"Authorization: {provide your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>JSON</td>
|
||||
<td>Location ID</td>
|
||||
<td>(Required) Location ID Example: curl https://api.teeseng.uk/api/v0/location/update
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"id": "7"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Location name</td>
|
||||
<td>JSON</td>
|
||||
<td>Location name.</td>
|
||||
<td>(Optional) Location name. Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"name":"Location name"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Added by </td>
|
||||
<td>JSON</td>
|
||||
<td>System or Admin</td>
|
||||
<td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"added_by":"system"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>JSON</td>
|
||||
<td>Description of Location</td>
|
||||
<td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"description":"test"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- delete location -->
|
||||
<div class="overflow-hidden content-section" id="content-update-location-by-id">
|
||||
<h2>Delete Location (Only for system or admin API key)</h2>
|
||||
<p>
|
||||
To delete an Location you need to make a DELETE call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/delete</code>
|
||||
<br>
|
||||
<br>
|
||||
Example :<br>
|
||||
<code
|
||||
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/delete -H "Content-Type: application/json" -X POST -d '{"id": "7"}'</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>Your API key.</td>
|
||||
<td>(Required) example: curl https://api.teeseng.uk/api/v0/location/delete -H
|
||||
"Authorization: {provide your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>JSON</td>
|
||||
<td>Location ID</td>
|
||||
<td>(Required) Location ID Example: curl https://api.teeseng.uk/api/v0/location/delete
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"id": "7"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="overflow-hidden content-section" id="content-errors">
|
||||
<h2>Errors</h2>
|
||||
<p>
|
||||
The Westeros API uses the following error codes:
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Error Code</th>
|
||||
<th>Meaning</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>X000</td>
|
||||
<td>
|
||||
Some parameters are missing. This error appears when you don't pass every mandatory
|
||||
parameters.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>403</td>
|
||||
<td>
|
||||
Unknown or unvalid <code class="higlighted">secret_key</code>. This error appears if
|
||||
you use an unknow API key or if your API key expired.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>500</td>
|
||||
<td>
|
||||
Unvalid <code class="higlighted">secret_key</code> No API key was supplied. Invalid
|
||||
request.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>X003</td>
|
||||
<td>
|
||||
Unknown or unvalid user <code class="higlighted">token</code>. This error appears if
|
||||
you use an unknow user <code class="higlighted">token</code> or if the user <code
|
||||
class="higlighted">token</code> expired.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="overflow-hidden content-section" id="content-get-api">
|
||||
<div class="api-keys-header">
|
||||
<h2>API Keys</h2>
|
||||
<div class="button-container">
|
||||
<button class="generate-key-button" onclick="generateKey()">Generate Key</button>
|
||||
<button class="delete-key-button" onclick="deleteKeys()">Delete Keys</button>
|
||||
</div>
|
||||
<div class="content-page">
|
||||
<div class="content">
|
||||
<div class="overflow-hidden content-section" id="content-get-started">
|
||||
<h1>Get started</h1>
|
||||
<p>
|
||||
You can generate API Keys here:
|
||||
The following API is provided by the Eco saver developer team. It allows you to get Location and
|
||||
Sensor and Sensor Data from the Eco saver database.
|
||||
</p>
|
||||
<p>
|
||||
To use this API, you need an <strong>API key</strong>.
|
||||
</p>
|
||||
</div>
|
||||
<div class="overflow-hidden content-section" id="content-get-location">
|
||||
<h2>Get all location</h2>
|
||||
<p>
|
||||
To get Location of sensors you need to make a GET call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location</code>
|
||||
<br>
|
||||
<br>
|
||||
Return Response :<br>
|
||||
<code class="higlighted break-word">{"status":"200"}</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Public Key</th>
|
||||
<th>Private Key</th>
|
||||
<th>Created</th>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>API Key</td>
|
||||
<td>GR234-We34</td>
|
||||
<td>greR-234-fEG</td>
|
||||
<td>2024-01-22</td>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>Your API key.</td>
|
||||
<td>(Required) Example: curl https://api.teeseng.uk/api/v0/location -H "Authorization:
|
||||
{provide your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="overflow-hidden content-section" id="content-get-location-by-id">
|
||||
<h2>Get location by ID</h2>
|
||||
<p>
|
||||
To get Location you need to make a GET call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/{id}</code>
|
||||
<br>
|
||||
<br>
|
||||
Return Response :<br>
|
||||
<code class="higlighted break-word">{"status":"200"}</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>(Required) Your API key.</td>
|
||||
<td>Example: curl https://api.teeseng.uk/api/v0/location -H "Authorization: {provide
|
||||
your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="overflow-hidden content-section" id="content-add-location">
|
||||
<h2>Add Location (Only for system or admin API key)</h2>
|
||||
<p>
|
||||
To add an Location you need to make a POST call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/new</code>
|
||||
<br>
|
||||
<br>
|
||||
Example :<br>
|
||||
<code
|
||||
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/new -H "Content-Type: application/json" -X POST -d '{"name": "SAMPLE", "added_by": "system" , "description": "test"}'</code>
|
||||
<br>
|
||||
<br>
|
||||
Return Response :<br>
|
||||
<code class="higlighted break-word">{"status":"200"}</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>Your API key.</td>
|
||||
<td>(Required) Example: curl https://api.teeseng.uk/api/v0/location/new -H
|
||||
"Authorization: {provide your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Location name</td>
|
||||
<td>JSON</td>
|
||||
<td>Location name.</td>
|
||||
<td>(Required) Location name. Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"name":"Location name"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Added by </td>
|
||||
<td>JSON</td>
|
||||
<td>System or Admin</td>
|
||||
<td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"added_by":"system"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>JSON</td>
|
||||
<td>Description of Location</td>
|
||||
<td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"description":"test"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- update -->
|
||||
<div class="overflow-hidden content-section" id="content-update-location-by-id">
|
||||
<h2>Update Location (Only for system or admin API key)</h2>
|
||||
<p>
|
||||
To update an Location you need to make a PUT call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/update</code>
|
||||
<br>
|
||||
<br>
|
||||
Example :<br>
|
||||
<code
|
||||
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/update -H "Content-Type: application/json" -X POST -d '{"id": "7" , "name": "SAMPLE", "added_by": "system" , "description": "test"}'</code>
|
||||
<br>
|
||||
<br>
|
||||
Return Response :<br>
|
||||
<code class="higlighted break-word">{"status":"200","message":"Location 7 updated"}</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>Your API key.</td>
|
||||
<td>(Required) example: curl https://api.teeseng.uk/api/v0/location/update -H
|
||||
"Authorization: {provide your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>JSON</td>
|
||||
<td>Location ID</td>
|
||||
<td>(Required) Location ID Example: curl https://api.teeseng.uk/api/v0/location/update
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"id": "7"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Location name</td>
|
||||
<td>JSON</td>
|
||||
<td>Location name.</td>
|
||||
<td>(Optional) Location name. Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"name":"Location name"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Added by </td>
|
||||
<td>JSON</td>
|
||||
<td>System or Admin</td>
|
||||
<td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"added_by":"system"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>JSON</td>
|
||||
<td>Description of Location</td>
|
||||
<td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/location/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"description":"test"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<!-- delete location -->
|
||||
<div class="overflow-hidden content-section" id="content-update-location-by-id">
|
||||
<h2>Delete Location (Only for system or admin API key)</h2>
|
||||
<p>
|
||||
To delete an Location you need to make a DELETE call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/location/delete</code>
|
||||
<br>
|
||||
<br>
|
||||
Example :<br>
|
||||
<code
|
||||
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/location/delete -H "Content-Type: application/json" -X POST -d '{"id": "7"}'</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>Your API key.</td>
|
||||
<td>(Required) example: curl https://api.teeseng.uk/api/v0/location/delete -H
|
||||
"Authorization: {provide your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>JSON</td>
|
||||
<td>Location ID</td>
|
||||
<td>(Required) Location ID Example: curl https://api.teeseng.uk/api/v0/location/delete
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"id": "7"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="overflow-hidden content-section" id="content-get-sensor">
|
||||
<h2>Get all sensor</h2>
|
||||
<p>
|
||||
To get sensors you need to make a GET call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/sensor</code>
|
||||
<br>
|
||||
<br>
|
||||
Return Response :<br>
|
||||
<code class="higlighted break-word">{"status":"200"}</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>Your API key.</td>
|
||||
<td>(Required) Example: curl https://api.teeseng.uk/api/v0/sensor -H "Authorization:
|
||||
{provide your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="overflow-hidden content-section" id="content-get-sensor-by-id">
|
||||
<h2>Get sensor by ID</h2>
|
||||
<p>
|
||||
To get Sensor you need to make a GET call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/sensor/{id}</code>
|
||||
<br>
|
||||
<br>
|
||||
Return Response :<br>
|
||||
<code class="higlighted break-word">{"status":"200"}</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>(Required) Your API key.</td>
|
||||
<td>Example: curl https://api.teeseng.uk/api/v0/sensor/{id} -H "Authorization: {provide
|
||||
your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="overflow-hidden content-section" id="content-add-sensor">
|
||||
<h2>Add Sensor (Only for system or admin API key)</h2>
|
||||
<p>
|
||||
To add a Sensor you need to make a POST call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/sensor/new</code>
|
||||
<br>
|
||||
<br>
|
||||
Example :<br>
|
||||
<code
|
||||
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/sensor/new -H "Content-Type: application/json" -X POST -d '{"sensorname": "test", "added_by": "system" , "mac_address": "99-6A-F8-7D-B4-94", "description": "test" , "location": "11"}'</code>
|
||||
<br>
|
||||
<br>
|
||||
Return Response :<br>
|
||||
<code class="higlighted break-word">{"status":"200"}</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>Your API key.</td>
|
||||
<td>(Required) Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||
-H "Authorization: {provide your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sensor name</td>
|
||||
<td>JSON</td>
|
||||
<td>Sesnsor name.</td>
|
||||
<td>(Required) Location name. Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"sensorname": "test"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Added by </td>
|
||||
<td>JSON</td>
|
||||
<td>System or Admin</td>
|
||||
<td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"added_by":"system"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mac Address</td>
|
||||
<td>JSON</td>
|
||||
<td>Mac Address</td>
|
||||
<td>(Required) Mac Address Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"mac_address": "99-6A-F8-7D-B4-94"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>JSON</td>
|
||||
<td>Description of Sensor</td>
|
||||
<td>(Required) System or Admin Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"description":"test"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mac Address</td>
|
||||
<td>JSON</td>
|
||||
<td>Mac Address</td>
|
||||
<td>(Required) Mac Address Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"mac_address": "99-6A-F8-7D-B4-94"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Location</td>
|
||||
<td>JSON</td>
|
||||
<td>Location</td>
|
||||
<td>(Required) Location Example: curl https://api.teeseng.uk/api/v0/sensor/new
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"location": "11"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="overflow-hidden content-section" id="content-update-sensor-by-id">
|
||||
<h2>Update Sensor (Only for system or admin API key)</h2>
|
||||
<p>
|
||||
To update a Sensor you need to make a PUT call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/sensor/update</code>
|
||||
<br>
|
||||
<br>
|
||||
Example :<br>
|
||||
<code
|
||||
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/sensor/update -H "Content-Type: application/json" -X POST -d '{"id": "2" ,"sensorname": "test", "added_by": "system" , "mac_address": "99-6A-F8-7D-B4-94" , "description": "test123" , "location": "11" }'</code>
|
||||
<br>
|
||||
<br>
|
||||
Return Response :<br>
|
||||
<code class="higlighted break-word">{"status":"200","message":"Sensor 2 updated"}</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>Your API key.</td>
|
||||
<td>(Required) example: curl https://api.teeseng.uk/api/v0/sensor/update -H
|
||||
"Authorization: {provide your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>JSON</td>
|
||||
<td>Sensor ID</td>
|
||||
<td>(Required) Sensor ID Example: curl https://api.teeseng.uk/api/v0/sensor/update
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"id": "7"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sensor name</td>
|
||||
<td>JSON</td>
|
||||
<td>Sensor name.</td>
|
||||
<td>(Optional) Sensor name. Example: curl https://api.teeseng.uk/api/v0/sensor/update
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"sensorname": "test"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Added by </td>
|
||||
<td>JSON</td>
|
||||
<td>System or Admin</td>
|
||||
<td>(Optional) System or Admin Example: curl https://api.teeseng.uk/api/v0/sensor/update
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"added_by":"system"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mac Address </td>
|
||||
<td>JSON</td>
|
||||
<td>Mac Address</td>
|
||||
<td>(Optional) Mac Address Example: curl https://api.teeseng.uk/api/v0/sensor/update
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"mac_address": "99-6A-F8-7D-B4-94"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<td>JSON</td>
|
||||
<td>Description of Sensor</td>
|
||||
<td>(Optional) Description of Sensor Example: curl
|
||||
https://api.teeseng.uk/api/v0/sensor/update
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"description":"test"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Location</td>
|
||||
<td>JSON</td>
|
||||
<td>Location of Sensor</td>
|
||||
<td>(Optional) Location of Sensor Example: curl
|
||||
https://api.teeseng.uk/api/v0/sensor/update
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"location": "11"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="overflow-hidden content-section" id="content-delete-sensor-by-id">
|
||||
<h2>Delete Sensor (Only for system or admin API key)</h2>
|
||||
<p>
|
||||
To delete a sensor you need to make a DELETE call to the following url :<br>
|
||||
<code class="higlighted break-word">https://api.teeseng.uk/api/v0/sensor/delete</code>
|
||||
<br>
|
||||
<br>
|
||||
Example :<br>
|
||||
<code
|
||||
class="higlighted break-word">curl https://api.teeseng.uk/api/v0/sensor/delete -H "Content-Type: application/json" -X POST -d '{"id": "7"}'</code>
|
||||
</p>
|
||||
<br>
|
||||
<h4>QUERY PARAMETERS</h4>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Authorization</td>
|
||||
<td>JSON</td>
|
||||
<td>Your API key.</td>
|
||||
<td>(Required) example: curl https://api.teeseng.uk/api/v0/sensor/delete -H
|
||||
"Authorization: {provide your
|
||||
API key here}"</td>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ID</td>
|
||||
<td>JSON</td>
|
||||
<td>Sensor ID</td>
|
||||
<td>(Required) Sensor ID Example: curl https://api.teeseng.uk/api/v0/sensor/delete
|
||||
-H "Authorization: provide
|
||||
your API key here" -d '{"id": "7"}'</td>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="api-keys-header iot-card" id="content-get-api">
|
||||
<h2>API Keys</h2>
|
||||
<p>
|
||||
You can generate API Keys here:
|
||||
</p>
|
||||
<form action="token/new" onsubmit="formAJAX(this)" class="api-form">
|
||||
<div class="card-header shadow actionMessage" style="display:none;"></div>
|
||||
<input type="email" name="email" id="email" placeholder="Email address"
|
||||
pattern="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">
|
||||
<div style="margin-top: 10px;"></div>
|
||||
<button class="generate-key-button">Generate Key</button>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overflow-hidden content-section" id="content-errors">
|
||||
<h2>Errors</h2>
|
||||
<p>
|
||||
The EcoSaver API uses the following error codes:
|
||||
</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Error Code</th>
|
||||
<th>Meaning</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>X000</td>
|
||||
<td>
|
||||
Some parameters are missing. This error appears when you don't pass every
|
||||
mandatory
|
||||
parameters.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>403</td>
|
||||
<td>
|
||||
Unknown or unvalid <code class="higlighted">secret_key</code>. This error
|
||||
appears if
|
||||
you use an unknow API key or if your API key expired.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>500</td>
|
||||
<td>
|
||||
Unvalid <code class="higlighted">secret_key</code> No API key was supplied.
|
||||
Invalid
|
||||
request.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>X003</td>
|
||||
<td>
|
||||
Unknown or unvalid user <code class="higlighted">token</code>. This error
|
||||
appears if
|
||||
you use an unknow user <code class="higlighted">token</code> or if the user
|
||||
<code class="higlighted">token</code> expired.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
<script src="js/api.js"></script>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
<script src="js/api.js"></script>
|
||||
<script src="js/apikey.js"></script>
|
||||
|
||||
</html>
|
||||
</html>
|
||||
|
@ -42,7 +42,8 @@
|
||||
</p>
|
||||
<p>
|
||||
<abbr title="Email">E</abbr>:
|
||||
<a href="mailto:name@example.com">leongdingxuan@gmail.com
|
||||
<a href="mailto:name@example.com">ecosaverx@gmail.com
|
||||
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
@ -55,17 +56,18 @@
|
||||
<!-- Contact Form -->
|
||||
<!-- In order to set the email address and subject line for the contact form go to the bin/contact_me.php file. -->
|
||||
<div class="row">
|
||||
<div class="form contact iot-card">
|
||||
<div class="col-lg-8 mb-4 contact-left">
|
||||
<h3>Send us a Message</h3>
|
||||
<form id="form">
|
||||
<input type="hidden" name="access_key" value="">
|
||||
<form action="auth/contact" onsubmit="formAJAX(this)">
|
||||
<div class="card-header shadow actionMessage" style="display:none"></div>
|
||||
<div class="mb-3">
|
||||
<label for="name">Full Name</label>
|
||||
<input type="text" name="name" id="name" required>
|
||||
<input type="text" name="name" id="name" required pattern="^[a-zA-Z]{3,}( {1,2}[a-zA-Z]{3,}){0,}$">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="email">Email address</label>
|
||||
<input type="email" name="email" id="email" required>
|
||||
<input type="email" name="email" id="email" required pattern="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="message">Message</label>
|
||||
@ -75,6 +77,8 @@
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- /.row -->
|
||||
|
@ -1,11 +1,60 @@
|
||||
<%- include('top') %>
|
||||
<script>
|
||||
//call socket.io
|
||||
app.socket.on("sensorData:new", function (data) {
|
||||
console.log("new data!!")
|
||||
console.log(data);
|
||||
<script type="text/javascript">
|
||||
function extractNumbers(str) {
|
||||
if (typeof str === 'number') return str;
|
||||
return str.match(/\d+/)[0];
|
||||
}
|
||||
|
||||
function calculateAverage(numbers) {
|
||||
if (numbers.length === 0) return 0
|
||||
const sum = numbers.reduce((acc, num) => acc + num, 0);
|
||||
return sum / numbers.length;
|
||||
}
|
||||
const values = {
|
||||
psi: [],
|
||||
humidity: [],
|
||||
temperature: [],
|
||||
windspeed: [],
|
||||
};
|
||||
|
||||
function parseRowToTemplace(row) {
|
||||
values.psi.unshift(extractNumbers(row.measurement.psi))
|
||||
values.humidity.unshift(extractNumbers(row.measurement.humidity))
|
||||
values.temperature.unshift(extractNumbers(row.measurement.temperature))
|
||||
values.windspeed.unshift(extractNumbers(row.measurement.windspeed))
|
||||
|
||||
return {
|
||||
average: {
|
||||
psi: parseInt(calculateAverage(values.psi)),
|
||||
humidity: parseInt(calculateAverage(values.humidity)),
|
||||
temperature: parseInt(calculateAverage(values.temperature)),
|
||||
windspeed: parseInt(calculateAverage(values.windspeed)),
|
||||
},
|
||||
latest: {
|
||||
psi: values.psi[0],
|
||||
humidity: values.humidity[0],
|
||||
temperature: values.temperature[0],
|
||||
windspeed: values.windspeed[0],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(async function () {
|
||||
|
||||
app.api.get('latest-sensor-data/data', function (error, data) {
|
||||
for (let row of data) {
|
||||
//console.log(row);
|
||||
$.scope.LatestSensorData.update(parseRowToTemplace(row));
|
||||
}
|
||||
});
|
||||
|
||||
//call socket.io to get live data
|
||||
app.socket.on("sensorData:new", function (data) {
|
||||
$.scope.LatestSensorData.update(parseRowToTemplace(data));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
@ -53,56 +102,60 @@
|
||||
</header>
|
||||
<!-- Page Content -->
|
||||
<div class="container">
|
||||
<div class="services-bar">
|
||||
<h1 class="my-4">Services</h1>
|
||||
<!-- Services Section -->
|
||||
<div class="row">
|
||||
<div class="col-lg-3 mb-4">
|
||||
<div class="card">
|
||||
<h4 class="card-header">Air Quality Index</h4>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text display-4">15 - 18 PSI</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||
</div>
|
||||
<div class="services-bar" jq-repeat="LatestSensorData">
|
||||
<h1 class="my-4">Services</h1>
|
||||
<!-- Services Section -->
|
||||
<div class="row">
|
||||
<div class="col-lg-3 mb-4">
|
||||
<div class="card">
|
||||
<h4 class="card-header">Air Quality Index</h4>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text display-4"> Average: {{average.psi}} PSI</p>
|
||||
<p class="card-text display-4"> Latest: {{latest.psi}} PSI</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 mb-4">
|
||||
<div class="card">
|
||||
<h4 class="card-header">Humidity</h4>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text display-4">70% - 75%</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 mb-4">
|
||||
<div class="card">
|
||||
<h4 class="card-header">Temperature</h4>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text display-4">30° - 37°</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 mb-4">
|
||||
<div class="card">
|
||||
<h4 class="card-header">Humidity</h4>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text display-4"> Average: {{average.humidity}} %</p>
|
||||
<p class="card-text display-4"> Latest: {{latest.humidity}} %</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 mb-4">
|
||||
<div class="card">
|
||||
<h4 class="card-header">Another Category</h4>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text display-4">values</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 mb-4">
|
||||
<div class="card">
|
||||
<h4 class="card-header">Temperature</h4>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text display-4"> Average: {{average.temperature}}°</p>
|
||||
<p class="card-text display-4"> Latest: {{latest.temperature}}°</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-3 mb-4">
|
||||
<div class="card">
|
||||
<h4 class="card-header">Wind Speed</h4>
|
||||
<div class="card-body text-center">
|
||||
<p class="card-text display-4"> Average: {{average.windspeed}} Km/h</p>
|
||||
<p class="card-text display-4"> Latest: {{latest.windspeed}} Km/h</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<a href="/learnmore" class="btn btn-primary">Learn More</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- /.row -->
|
||||
</div>
|
||||
<!-- About Section -->
|
||||
|
@ -27,7 +27,7 @@
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.1/mustache.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.1/mustache.js"></script>
|
||||
<!-- socket.io scriot -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.min.js"></script>
|
||||
|
||||
<!-- jquery app.js -->
|
||||
<script src="js/app.js"></script>
|
||||
@ -44,19 +44,22 @@
|
||||
$(document).ready(function () {
|
||||
//check if user is logged in
|
||||
app.auth.isLoggedIn(function (error, data) {
|
||||
if (data) {
|
||||
$('#cl-logout-button').show('fast');
|
||||
$('#cl-profile-button').show('fast');
|
||||
$('#cl-login-button').hide('fast');
|
||||
if (!error) {
|
||||
$("#cl-logout-button").show("fast");
|
||||
$("#cl-api-button").show("fast");
|
||||
$("#cl-profile-button").show("fast");
|
||||
$("#cl-login-button").hide("fast");
|
||||
|
||||
} else {
|
||||
$('#cl-login-button').show('fast');
|
||||
|
||||
}
|
||||
$('body').show('fast')
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
</script>
|
||||
|
||||
|
||||
<nav class="navbar fixed-top navbar-expand-lg navbar-dark bg-light top-nav fixed-top">
|
||||
@ -79,11 +82,12 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/contact">Contact</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/api">API Doc</a>
|
||||
</li>
|
||||
<!-- profile button -->
|
||||
<div class="form-inline mt-2 mt-md-0">
|
||||
<a id="cl-api-button" class="btn btn-outline-info btn-sm my-2 my-sm-0" href="/api"
|
||||
style="display: none">
|
||||
<i class="fas fa-sign-out"></i> API
|
||||
</a>
|
||||
<a id="cl-profile-button" class="btn btn-outline-info my-2 my-sm-0" href="/profile"
|
||||
style="display: none;">
|
||||
<i class="fas fa-sign-out"></i>
|
||||
@ -103,5 +107,4 @@
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
</nav>
|
@ -1,4 +1,8 @@
|
||||
<%- include('top') %>
|
||||
<script type="text/javascript">
|
||||
// Require login to see this page.
|
||||
app.auth.forceLogin()
|
||||
</script>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
@ -6,9 +10,9 @@
|
||||
<div class="profile">
|
||||
<!-- <li jq-repeat="getUsername" class="nav-item"> -->
|
||||
<div class="edit_information" jq-repeat="getUserDetails">
|
||||
<div class="card-header shadow actionMessage" style="display:none"></div>
|
||||
<form id="profileForm" action="user/update" method="put" onsubmit="formAJAX(this)"
|
||||
evalAJAX="app.auth.profileRedirect();">
|
||||
<div class="card-header shadow actionMessage" style="display:none"></div>
|
||||
<h3 class="text-center">Edit Personal Information</h3>
|
||||
<br>
|
||||
<div class="row">
|
||||
|
@ -8,10 +8,9 @@
|
||||
|
||||
<ul id="sensorDataList">
|
||||
<li jq-repeat='sensorData'>
|
||||
rowid: {{ id }}
|
||||
sensorId: {{ sensorid }}
|
||||
created: {{ createdAt }}
|
||||
location: {{ locationid }}
|
||||
created: {{ createdAt }}
|
||||
<br />
|
||||
co: {{ measurement.co }}
|
||||
humidity: {{ measurement.humidity }}
|
||||
@ -30,7 +29,7 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
$(document).ready(async function () {
|
||||
app.api.get('sensor-data/data?order=DESC&limit=40', function(error, data){
|
||||
app.api.get('sensor-data/data?order=DESC&limit=6', function(error, data){
|
||||
$.scope.sensorData.push(...data);
|
||||
})
|
||||
})
|
||||
|
@ -57,9 +57,7 @@
|
||||
//check if user is logged in
|
||||
app.auth.isLoggedIn(function (error, data) {
|
||||
if (!error) {
|
||||
console.log(error);
|
||||
$.scope.getUsername.update(data);
|
||||
|
||||
if (location.pathname == "/profile") {
|
||||
$.scope.getUserDetails.update(data);
|
||||
}
|
||||
|
Reference in New Issue
Block a user