initial commit: dht client
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/node_modules
|
||||||
134
charts.html
Normal file
134
charts.html
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
|
||||||
|
<script>
|
||||||
|
var current;
|
||||||
|
window.onload = function () {
|
||||||
|
var dataPoints1 = [];
|
||||||
|
var dataPoints2 = [];
|
||||||
|
/*{ x: new Date(2017, 0, 3), y: 650 },
|
||||||
|
{ x: new Date(2017, 0, 4), y: 700 },
|
||||||
|
*/
|
||||||
|
|
||||||
|
var chart = new CanvasJS.Chart("chartContainer", {
|
||||||
|
animationEnabled: true,
|
||||||
|
theme: "light2",
|
||||||
|
zoomEnabled: true,
|
||||||
|
zoomType: "x",
|
||||||
|
exportEnabled: true,
|
||||||
|
title:{
|
||||||
|
text: "Retrieving current A23 conditions..."
|
||||||
|
},
|
||||||
|
/* subtitles:[{
|
||||||
|
text: "X Axis scale is Logarithmic",
|
||||||
|
fontSize: 14
|
||||||
|
}],*/
|
||||||
|
axisX:{
|
||||||
|
valueFormatString: "HH:mm DD MMM",
|
||||||
|
crosshair: {
|
||||||
|
enabled: true,
|
||||||
|
snapToDataPoint: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisY: {
|
||||||
|
title: "Temperature",
|
||||||
|
lineColor: "#C24642",
|
||||||
|
titleFontColor: "#C24642",
|
||||||
|
labelFontColor: "#C24642",
|
||||||
|
crosshair: {
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisY2: [
|
||||||
|
{
|
||||||
|
title: "Relative hum %",
|
||||||
|
titleFontColor: "#51CDA0",
|
||||||
|
labelFontColor: "#51CDA0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
//{title: "Temperature",
|
||||||
|
//lineColor: "#C24642",
|
||||||
|
//titleFontColor: "#C0504E",
|
||||||
|
//labelFontColor: "#C0504E"
|
||||||
|
//},
|
||||||
|
toolTip:{
|
||||||
|
shared:true
|
||||||
|
},
|
||||||
|
legend:{
|
||||||
|
cursor:"pointer",
|
||||||
|
verticalAlign: "bottom",
|
||||||
|
horizontalAlign: "left",
|
||||||
|
dockInsidePlotArea: true,
|
||||||
|
itemclick: toogleDataSeries
|
||||||
|
},
|
||||||
|
data: [{
|
||||||
|
name: "Temperature",
|
||||||
|
type: "spline",//line
|
||||||
|
showInLegend: true,
|
||||||
|
markerType: "square",
|
||||||
|
xValueFormatString: "HH:mm on DD MMM, YYYY",
|
||||||
|
color: "#F08080",
|
||||||
|
dataPoints: dataPoints2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Humidiry",
|
||||||
|
type: "spline",
|
||||||
|
axisYType: "secondary",
|
||||||
|
axisYIndex: 1,
|
||||||
|
showInLegend: true,
|
||||||
|
lineDashType: "dash",
|
||||||
|
dataPoints: dataPoints1
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function toogleDataSeries(e){
|
||||||
|
if (typeof(e.dataSeries.visible) === "undefined" || e.dataSeries.visible) {
|
||||||
|
e.dataSeries.visible = false;
|
||||||
|
} else {
|
||||||
|
e.dataSeries.visible = true;
|
||||||
|
}
|
||||||
|
chart.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
function addData(data) {
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
if(data[i].field_name == "A23_DHT"){
|
||||||
|
var dht = JSON.parse(data[i].field_value).dht;
|
||||||
|
var date = new Date(data[i]["timestamp"]);
|
||||||
|
if(dht && dht.hum <= 100){
|
||||||
|
dataPoints1.push({
|
||||||
|
x: date,
|
||||||
|
y: dht.hum
|
||||||
|
});
|
||||||
|
dataPoints2.push({
|
||||||
|
x: date,
|
||||||
|
y: dht.temp
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chart.render();
|
||||||
|
|
||||||
|
$.getJSON("/n/dht", function(data){
|
||||||
|
if(data && data.dht){
|
||||||
|
chart.title.set("text", "A23 Currently is " + data.dht.temp + "°C, " + data.dht.hum +"% RH" );
|
||||||
|
}else {
|
||||||
|
chart.title.set("text", "A23 conditions");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$.getJSON("/n/dht/A23_DHT", addData);
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="chartContainer" style="height: 370px; width: 100%;"></div>
|
||||||
|
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
211
dht.js
Normal file
211
dht.js
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
// ./src/index.js
|
||||||
|
|
||||||
|
// importing the dependencies
|
||||||
|
const express = require('express');
|
||||||
|
const bodyParser = require('body-parser');
|
||||||
|
const cors = require('cors');
|
||||||
|
const helmet = require('helmet');
|
||||||
|
const morgan = require('morgan');
|
||||||
|
const cron = require('node-cron');
|
||||||
|
const request = require('request');
|
||||||
|
const got = require('got');
|
||||||
|
const Sequelize = require("sequelize")
|
||||||
|
|
||||||
|
//!https endpoint
|
||||||
|
var fs = require("fs");
|
||||||
|
var http = require('http');
|
||||||
|
var https = require('https');
|
||||||
|
var privateKey = fs.readFileSync('/etc/letsencrypt/live/iot.d-popov.com/privkey.pem', 'utf8');
|
||||||
|
var certificate = fs.readFileSync('/etc/letsencrypt/live/iot.d-popov.com/cert.pem', 'utf8');
|
||||||
|
var credentials = {key: privateKey, cert: certificate};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//!database
|
||||||
|
var mysql = require('mysql');
|
||||||
|
var con = mysql.createConnection({
|
||||||
|
host : 'localhost',
|
||||||
|
user : 'iot',
|
||||||
|
password : '!iot_popovi',
|
||||||
|
database : 'iot'
|
||||||
|
});
|
||||||
|
var sqlz = new Sequelize('iot', 'iot', '!iot_popovi',{dialect: 'mysql'})
|
||||||
|
|
||||||
|
const mongoose = require('mongoose');
|
||||||
|
const Schema = mongoose.Schema;
|
||||||
|
|
||||||
|
let DeviceMessageSchema = new Schema({
|
||||||
|
_id: {type: Number, required: true},
|
||||||
|
device_id: {type: String, required: true, max: 100}
|
||||||
|
});
|
||||||
|
|
||||||
|
let DevicesSchema = new Schema({
|
||||||
|
id: {type: Number, required: true},
|
||||||
|
url: {type: String, required: true, max: 100}
|
||||||
|
});
|
||||||
|
|
||||||
|
var Device = sqlz.define('device', {
|
||||||
|
id: { type: Sequelize.INTEGER, autoIncrement: true, primaryKey: true },
|
||||||
|
name: Sequelize.STRING,
|
||||||
|
baseurl: Sequelize.TEXT,
|
||||||
|
apikey: Sequelize.TEXT,
|
||||||
|
//config: Sequelize.JSON,
|
||||||
|
lastseen: Sequelize.DATE
|
||||||
|
});
|
||||||
|
|
||||||
|
sqlz.sync();
|
||||||
|
|
||||||
|
|
||||||
|
// defining the Express app
|
||||||
|
const app = express();
|
||||||
|
var httpServer = http.createServer(app);
|
||||||
|
var httpsServer = https.createServer(credentials, app);
|
||||||
|
|
||||||
|
// defining an array to work as the database (temporary solution)
|
||||||
|
const ads = [
|
||||||
|
{title: 'Hello, world (again)!'}
|
||||||
|
];
|
||||||
|
|
||||||
|
// adding Helmet to enhance your API's security
|
||||||
|
app.use(helmet());
|
||||||
|
|
||||||
|
// using bodyParser to parse JSON bodies into JS objects
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
|
||||||
|
// enabling CORS for all requests
|
||||||
|
app.use(cors());
|
||||||
|
|
||||||
|
// adding morgan to log HTTP requests
|
||||||
|
app.use(morgan('combined'));
|
||||||
|
|
||||||
|
// defining an endpoint to return all ads
|
||||||
|
app.get('/dht', (req, res) => { (async (res) => {
|
||||||
|
try {
|
||||||
|
const response = await got('http://192.168.1.126/json')
|
||||||
|
res.send(response.body);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("DHT Error:" + error); //..response.body);
|
||||||
|
} })(res);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get("/dht/:field_name", (req, res) => {
|
||||||
|
dht = con.query("SELECT * FROM devicemessages WHERE field_name=? OR ? IS NULL",
|
||||||
|
[req.params.field_name, req.params.field_name], (err, data) => {
|
||||||
|
//dht = con.query("SELECT * FROM devicemessages", (err, data) => {
|
||||||
|
if (!err) {
|
||||||
|
res.send(data);
|
||||||
|
} else {
|
||||||
|
console.log("error: ", err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.put('/dht/:device_id/:field_name/:field_value', (req, res) => {
|
||||||
|
var params = [req.params.device_id,req.params.field_name,req.params.field_value];
|
||||||
|
let sql = `INSERT INTO devicemessages(device_id,field_name,field_value,timestamp)
|
||||||
|
VALUES (?,?,?,NOW());`;
|
||||||
|
con.query(sql,params, (err, r) => {
|
||||||
|
if (err) {
|
||||||
|
console.log("error: ", err);
|
||||||
|
res.send( err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r.affectedRows == 0) {
|
||||||
|
// not found Customer with the id
|
||||||
|
res.send({ kind: "not_found" });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("inserted record: ", { id: r.insertId, ...params });
|
||||||
|
res.send( { id: r.insertId, ...params });
|
||||||
|
});
|
||||||
|
//con.end();
|
||||||
|
|
||||||
|
//fs.appendFileSync('dht.txt', 'data to append');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
httpsServer.listen(8443, () => {
|
||||||
|
console.log('HTTPS server listening on port 8443');
|
||||||
|
});
|
||||||
|
httpServer.listen(81, () => {
|
||||||
|
console.log('HTTP server listening on port 81');
|
||||||
|
});
|
||||||
|
var device = Device.build({
|
||||||
|
name: 'A23',
|
||||||
|
url: "http://192.168.1.126/"
|
||||||
|
});
|
||||||
|
// device.save().then().catch(
|
||||||
|
// err => {console.log(err);}
|
||||||
|
// )
|
||||||
|
//.success(function(savedTask) {
|
||||||
|
// console.log('device saved with id' + savedTask.id);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// # ┌────────────── second (optional)
|
||||||
|
// # │ ┌──────────── minute
|
||||||
|
// # │ │ ┌────────── hour
|
||||||
|
// # │ │ │ ┌──────── day of month
|
||||||
|
// # │ │ │ │ ┌────── month
|
||||||
|
// # │ │ │ │ │ ┌──── day of week
|
||||||
|
// # │ │ │ │ │ │
|
||||||
|
// # │ │ │ │ │ │
|
||||||
|
// # * * * * * *
|
||||||
|
cron.schedule(' */30 * * * *', () => {//cron.schedule('*/5 * * * * *', () => {
|
||||||
|
console.log(new Date().toISOString() + ' running a task every 30 minutes');
|
||||||
|
StoreSensorReadingsAsync();
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
StoreSensorReadings();
|
||||||
|
|
||||||
|
async function StoreSensorReadingsAsync()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
await new Promise(function(resolve, reject) {
|
||||||
|
request('http://192.168.1.126/json', { json: true }, (err, res, body) => {
|
||||||
|
if(err) {
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var params = [0, "A23_DHT", JSON.stringify(body)];
|
||||||
|
let sql = `INSERT INTO devicemessages(device_id,field_name,field_value,timestamp)
|
||||||
|
VALUES (?,?,?,NOW());`;
|
||||||
|
con.query(sql,params,(err, r) => {
|
||||||
|
if (err) {
|
||||||
|
console.log("error: ", err);
|
||||||
|
}else{
|
||||||
|
console.log("inserted record: ", { id: r.insertId, ...params });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
resolve(body);
|
||||||
|
console.log(body);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} catch(error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function StoreSensorReadings()
|
||||||
|
{
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const dht = await got('http://192.168.1.126/json')
|
||||||
|
|
||||||
|
var params = [0, "A23_DHT", dht.body];
|
||||||
|
let sql = `INSERT INTO devicemessages(device_id,field_name,field_value,timestamp)
|
||||||
|
VALUES (?,?,?,NOW());`;
|
||||||
|
con.query(sql,params,(err, r) => {
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
}else{
|
||||||
|
console.log("inserted record: ", { id: r.insertId, ...params });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.log("DHT Error:" + error); //..response.body);
|
||||||
|
} })();
|
||||||
|
}
|
||||||
58
index.js
Normal file
58
index.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
// ./src/index.js
|
||||||
|
|
||||||
|
// importing the dependencies
|
||||||
|
const express = require('express');
|
||||||
|
const bodyParser = require('body-parser');
|
||||||
|
const cors = require('cors');
|
||||||
|
const helmet = require('helmet');
|
||||||
|
const morgan = require('morgan');
|
||||||
|
|
||||||
|
var fs = require("fs");
|
||||||
|
var http = require('http');
|
||||||
|
var https = require('https');
|
||||||
|
var privateKey = fs.readFileSync('/etc/letsencrypt/live/zbor.eu.org/privkey.pem', 'utf8');
|
||||||
|
var certificate = fs.readFileSync('/etc/letsencrypt/live/zbor.eu.org/cert.pem', 'utf8');
|
||||||
|
|
||||||
|
var credentials = {key: privateKey, cert: certificate};
|
||||||
|
|
||||||
|
// defining the Express app
|
||||||
|
const app = express();
|
||||||
|
var httpServer = http.createServer(app);
|
||||||
|
var httpsServer = https.createServer(credentials, app);
|
||||||
|
|
||||||
|
// defining an array to work as the database (temporary solution)
|
||||||
|
const ads = [
|
||||||
|
{title: 'Hello, world (again)!'}
|
||||||
|
];
|
||||||
|
|
||||||
|
// adding Helmet to enhance your API's security
|
||||||
|
app.use(helmet());
|
||||||
|
|
||||||
|
// using bodyParser to parse JSON bodies into JS objects
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
|
||||||
|
// enabling CORS for all requests
|
||||||
|
app.use(cors());
|
||||||
|
|
||||||
|
// adding morgan to log HTTP requests
|
||||||
|
app.use(morgan('combined'));
|
||||||
|
|
||||||
|
// defining an endpoint to return all ads
|
||||||
|
app.get('/', (req, res) => {
|
||||||
|
res.send(ads);
|
||||||
|
});
|
||||||
|
app.get('/dht', (req, res) => {
|
||||||
|
res.send("DHT");
|
||||||
|
});
|
||||||
|
|
||||||
|
// starting the server
|
||||||
|
//app.listen(3001, () => {
|
||||||
|
//console.log('listening on port 3001');
|
||||||
|
//});
|
||||||
|
|
||||||
|
// httpServer.listen(8080, () => {
|
||||||
|
// console.log('httpServer listening on port 8080');
|
||||||
|
// });
|
||||||
|
httpsServer.listen(8443, () => {
|
||||||
|
console.log('httpsServer listening on port 8443');
|
||||||
|
});
|
||||||
1001
logs/devicemessages.csv
Normal file
1001
logs/devicemessages.csv
Normal file
File diff suppressed because it is too large
Load Diff
1910
package-lock.json
generated
Normal file
1910
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
39
package.json
Normal file
39
package.json
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"name": "iot-rest-api",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": " test api for IOT devices",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": ""
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"bugs": {
|
||||||
|
"url": ""
|
||||||
|
},
|
||||||
|
"homepage": "",
|
||||||
|
"dependencies": {
|
||||||
|
"body-parser": "^1.19.0",
|
||||||
|
"cors": "2.8.5",
|
||||||
|
"express": "^4.8.7",
|
||||||
|
"got": "^10.7.0",
|
||||||
|
"helmet": "3.21.3",
|
||||||
|
"jsonwebtoken": "^7.3.0",
|
||||||
|
"moment": "^2.17.1",
|
||||||
|
"moment-timezone": "^0.5.13",
|
||||||
|
"mongoose": "^5.9.5",
|
||||||
|
"morgan": "^1.9.1",
|
||||||
|
"mysql": "^2.18.1",
|
||||||
|
"mysql2": "^2.1.0",
|
||||||
|
"node-cron": "^2.0.3",
|
||||||
|
"node-uuid": "^1.4.8",
|
||||||
|
"request": "^2.88.2",
|
||||||
|
"sequelize": "^5.21.5",
|
||||||
|
"swagger-ui-express": "^2.0.13",
|
||||||
|
"sync-request": "^4.0.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
30
schema.sql
Normal file
30
schema.sql
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
DROP TABLE IF EXISTS `devicemessages`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8 */;
|
||||||
|
CREATE TABLE `devicemessages` (
|
||||||
|
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||||
|
`device_id` int(20) NOT NULL,
|
||||||
|
`field_name` varchar(120) NOT NULL,
|
||||||
|
`field_value` text NOT NULL,
|
||||||
|
`timestamp` datetime NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1350 DEFAULT CHARSET=utf8;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `devices`;
|
||||||
|
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||||
|
/*!40101 SET character_set_client = utf8 */;
|
||||||
|
CREATE TABLE `devices` (
|
||||||
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`name` varchar(255) DEFAULT NULL,
|
||||||
|
`baseurl` text DEFAULT NULL,
|
||||||
|
`apikey` text DEFAULT NULL,
|
||||||
|
`config` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
|
||||||
|
`lastseen` datetime DEFAULT NULL,
|
||||||
|
`createdAt` datetime NOT NULL,
|
||||||
|
`updatedAt` datetime NOT NULL,
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
|
||||||
|
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||||
Reference in New Issue
Block a user