Update formAJAX function to log data from the server Add getUserByEmail and checkEmail functions Update profile.ejs to require login Update addSensorData function to emit new sensor data Update api.css with styling changes Update token route to generate and send token email Update authChecker middleware to allow user and token routes
277 lines
6.2 KiB
HTML
277 lines
6.2 KiB
HTML
<%- include('top') %>
|
|
<style>
|
|
#sensorDataAverage {
|
|
padding-top: 2.5em;
|
|
padding-bottom: 2.5em;
|
|
}
|
|
</style>
|
|
|
|
<div class="container">
|
|
|
|
<div class="row" id="sensorDataAverage" jq-repeat='sensorDataAverage'>
|
|
|
|
<div class="col-md-3">
|
|
<div id="workerStatusCard" class="card shadow-lg">
|
|
<h5 class="card-header">
|
|
Air Quality Index
|
|
</h5>
|
|
<div class="card-body">
|
|
Average: {{average.aqi}}
|
|
<br />
|
|
latest: {{latest.aqi}}
|
|
</div>
|
|
<div class="card-footer">
|
|
<button type="button" class="btn btn-success">
|
|
Learn More
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-3">
|
|
<div id="workerStatusCard" class="card shadow-lg">
|
|
<h5 class="card-header">
|
|
Humidity
|
|
</h5>
|
|
<div class="card-body">
|
|
Average: {{average.humidity}}
|
|
<br />
|
|
latest: {{latest.humidity}}
|
|
</div>
|
|
<div class="card-footer">
|
|
<button type="button" class="btn btn-success">
|
|
Learn More
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-3">
|
|
<div id="workerStatusCard" class="card shadow-lg">
|
|
<h5 class="card-header">
|
|
Temperature
|
|
</h5>
|
|
<div class="card-body">
|
|
Average: {{average.temperature}}
|
|
<br />
|
|
latest: {{latest.temperature}}
|
|
</div>
|
|
<div class="card-footer">
|
|
<button type="button" class="btn btn-success">
|
|
Learn More
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-3">
|
|
<div id="workerStatusCard" class="card shadow-lg">
|
|
<h5 class="card-header">
|
|
Wind Speed
|
|
</h5>
|
|
<div class="card-body">
|
|
Average: {{average.windspeed}}
|
|
<br />
|
|
latest: {{latest.windspeed}}
|
|
</div>
|
|
<div class="card-footer">
|
|
<button type="button" class="btn btn-success">
|
|
Learn More
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row" jq-repeat-defualt='sensorDataAverage'>
|
|
Loading...
|
|
</div>
|
|
</div>
|
|
|
|
<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 = {
|
|
aqi: [],
|
|
humidity: [],
|
|
temperature: [],
|
|
windspeed: [],
|
|
};
|
|
|
|
function parseRowToTemplace(row){
|
|
|
|
values.aqi.unshift(extractNumbers(row.measurement.o3))
|
|
values.humidity.unshift(extractNumbers(row.measurement.humidity))
|
|
values.temperature.unshift(extractNumbers(row.measurement.temperature))
|
|
values.windspeed.unshift(extractNumbers(row.measurement.windspeed))
|
|
|
|
return {
|
|
average: {
|
|
aqi: parseInt(calculateAverage(values.aqi)),
|
|
humidity: parseInt(calculateAverage(values.humidity)),
|
|
temperature: parseInt(calculateAverage(values.temperature)),
|
|
windspeed: parseInt(calculateAverage(values.windspeed)),
|
|
},
|
|
latest: {
|
|
aqi: values.humidity[0],
|
|
humidity: values.humidity[0],
|
|
temperature: values.humidity[0],
|
|
windspeed: values.windspeed[0],
|
|
}
|
|
}
|
|
}
|
|
|
|
$(document).ready(async function () {
|
|
app.api.get('sensor-data/data?order=DESC&limit=40', function(error, data){
|
|
for(let row of data){
|
|
$.scope.sensorDataAverage.update(parseRowToTemplace(row));
|
|
}
|
|
});
|
|
|
|
app.socket.on('sensorData:new', function(row){
|
|
$.scope.sensorDataAverage.update(parseRowToTemplace(row));
|
|
})
|
|
});
|
|
</script>
|
|
<%- include('bot') %>
|
|
|
|
<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>
|
|
|
|
|
|
<div class="overflow-hidden content-section" id="content-get-api">
|
|
<div class="api-keys-header">
|
|
<h2>API Keys</h2>
|
|
<button class="generate-key-button">Generate Key</button>
|
|
<p>
|
|
You can generate API Keys here:
|
|
</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Public Key</th>
|
|
<th>Private Key</th>
|
|
<th>Key Type</th>
|
|
<th>Created</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>API Key</td>
|
|
<td>GR234-We34</td>
|
|
<td>greR-234-fEG</td>
|
|
<td>Type</td>
|
|
<td>2024-01-22</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</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>
|
|
<button class="generate-key-button">Generate Key</button>
|
|
<p>
|
|
You can generate API Keys here:
|
|
</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Public Key</th>
|
|
<th>Private Key</th>
|
|
<th>Key Type</th>
|
|
<th>Created</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>API Key</td>
|
|
<td>GR234-We34</td>
|
|
<td>greR-234-fEG</td>
|
|
<td>Type</td>
|
|
<td>2024-01-22</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<div class="api-keys-header">
|
|
<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" required pattern="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">
|
|
<div style="margin-top: 10px;"></div> <!-- Adjust margin-top value as needed -->
|
|
<input type="submit" value="Generate Key">
|
|
</form>
|
|
</div> |