This commit is contained in:
Leo
2024-01-27 05:54:35 +08:00
34 changed files with 2039 additions and 610 deletions

View File

@ -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,
});
}
});

View File

@ -107,4 +107,6 @@ const sensorModel = sequelize.define(
}
);
sensorModel.belongsTo(locationModel);
module.exports = { sensorModel };

View File

@ -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",
{

View File

@ -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')),
},
},

View File

@ -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 };

View File

@ -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 };

View 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 };

View File

@ -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,
};

View File

@ -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
};

View File

@ -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;
}
*/

View File

@ -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',

View File

@ -3812,6 +3812,7 @@
.card-text {
color: #000000;
font-size: 16px;
}
/* edit profile */

View File

@ -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 */
}

View File

@ -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");

View File

@ -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;

View File

@ -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;

View 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;

View File

@ -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);

View File

@ -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,
});

View File

@ -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>

View File

@ -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 -->

View File

@ -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&deg; - 37&deg;</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}}&deg;</p>
<p class="card-text display-4"> Latest: {{latest.temperature}}&deg;</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 -->

View File

@ -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>

View File

@ -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">

View File

@ -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);
})
})

View File

@ -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);
}