initial commit
This commit is contained in:
commit
6f1b1fa649
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
node_modules/
|
||||
config.json
|
2613
package-lock.json
generated
Normal file
2613
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
17
package.json
Normal file
17
package.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "wetterkram",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "src/index.mjs",
|
||||
"scripts": {
|
||||
"start": "node --experimental-json-modules src/index.mjs"
|
||||
},
|
||||
"author": "Flummi",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"mariadb": "^2.5.4",
|
||||
"sharp": "^0.28.3",
|
||||
"slimbot": "^5.1.0",
|
||||
"superagent": "^6.1.0"
|
||||
}
|
||||
}
|
5
src/graph.mjs
Normal file
5
src/graph.mjs
Normal file
|
@ -0,0 +1,5 @@
|
|||
import graph from "./inc/graph.mjs";
|
||||
|
||||
(async () => {
|
||||
console.log(await graph("pressure"));
|
||||
})();
|
88
src/inc/graph.mjs
Normal file
88
src/inc/graph.mjs
Normal file
|
@ -0,0 +1,88 @@
|
|||
import sql from "./sql.mjs";
|
||||
import cfg from "../../config.json";
|
||||
import lib from "./lib.mjs";
|
||||
import sharp from "sharp";
|
||||
import superagent from "superagent";
|
||||
import { spawn } from "child_process";
|
||||
|
||||
const types = {
|
||||
temperature: "Temperature (°C)",
|
||||
humidity: "Humidity (%)",
|
||||
pressure: "Pressure (hPa)",
|
||||
gas: "Gas (KOhms)",
|
||||
light: "Light"
|
||||
};
|
||||
|
||||
const gnuplot = (q, _buf = []) => new Promise((resolve, reject) => {
|
||||
const plot = spawn("gnuplot");
|
||||
plot.stdin.write(Buffer.from(q));
|
||||
plot.stdout.on('data', chunk => _buf.push(chunk));
|
||||
plot.stdout.on('end', () => resolve(Buffer.concat(_buf)));
|
||||
plot.stdout.on('error', err => reject(err));
|
||||
});
|
||||
|
||||
export default async type => {
|
||||
type = type.toLowerCase();
|
||||
if(!Object.keys(types).includes(type)) {
|
||||
return {
|
||||
success: false,
|
||||
msg: "unknown type"
|
||||
};
|
||||
}
|
||||
|
||||
const query = `
|
||||
select
|
||||
date_format(from_unixtime(sub.stamp), '%Y-%m-%d %H:%i:%S') as stamp,
|
||||
sub.${type}
|
||||
from (
|
||||
select
|
||||
stamp,
|
||||
${type}
|
||||
from weather_data_bme680
|
||||
order by stamp desc
|
||||
limit 300
|
||||
) sub
|
||||
order by stamp asc`;
|
||||
|
||||
let data = await sql.query(query);
|
||||
data = lib.convertToCSV(["Time", type], data);
|
||||
|
||||
const q = `unset key
|
||||
set term svg size 600,400
|
||||
set datafile separator ","
|
||||
set xlabel "Time"
|
||||
set ylabel "${types[type]}"
|
||||
set grid xtics lw 1 lc rgb "#dddddd"
|
||||
set grid ytics lw 1 lc rgb "#dddddd"
|
||||
set xtics rotate by 45 right
|
||||
set xdata time
|
||||
set timefmt "%Y-%m-%d %H:%M:%S"
|
||||
format x "%H:%M:%S"
|
||||
$D << EOD\n${data}\nEOD
|
||||
plot for [col=2:2] $D using 1:col with lines
|
||||
dump
|
||||
quit\n`;
|
||||
|
||||
const out = await gnuplot(q);
|
||||
|
||||
const file = await sharp(out)
|
||||
.flatten({ background: '#ffffff' })
|
||||
.png()
|
||||
.toBuffer();
|
||||
|
||||
try {
|
||||
const res = JSON.parse((await superagent
|
||||
.post(`https://f0ck.space/upgraph.php`)
|
||||
.field("topsecret", cfg.uploadkey)
|
||||
.attach("image", file, "out.png")).text);
|
||||
return {
|
||||
success: true,
|
||||
link: res.data.link
|
||||
};
|
||||
} catch(err) {
|
||||
return {
|
||||
success: false,
|
||||
msg: err.msg
|
||||
};
|
||||
}
|
||||
};
|
64
src/inc/lib.mjs
Normal file
64
src/inc/lib.mjs
Normal file
|
@ -0,0 +1,64 @@
|
|||
export default new class {
|
||||
calculateHeatIndexCelcius(temperature, humidity) {
|
||||
return +(
|
||||
-8.784695 + 1.61139411 * temperature + 2.33854900 * humidity +
|
||||
-0.14611605 * temperature * humidity + -0.01230809 * temperature ** 2 +
|
||||
-0.01642482 * humidity ** 2 + 0.00221173 * temperature ** 2 * humidity +
|
||||
0.00072546 * temperature * humidity ** 2 +
|
||||
-0.00000358 * temperature ** 2 * humidity ** 2
|
||||
).toFixed(2);
|
||||
};
|
||||
|
||||
calculateDewPointCelcius(temperature, humidity) {
|
||||
return +(
|
||||
243.04 * (Math.log(humidity / 100.0) + ((17.625 * temperature) / (243.04 + temperature))) /
|
||||
(17.625 - Math.log(humidity / 100.0) - ((17.625 * temperature) / (243.04 + temperature)))
|
||||
).toFixed(2);
|
||||
};
|
||||
|
||||
getInline() {
|
||||
return JSON.stringify({
|
||||
inline_keyboard: [[
|
||||
{ text: "📈 temperature", callback_data: 'g_temperature' },
|
||||
{ text: "📈 pressure", callback_data: 'g_pressure' }
|
||||
], [
|
||||
{ text: "📈 light", callback_data: 'g_light' },
|
||||
{ text: "📈 humidity", callback_data: 'g_humidity' }
|
||||
], [
|
||||
{ text: "📈 gas", callback_data: 'g_gas' },
|
||||
{ text: "❌ remove graph", callback_data: 'g_remove' }
|
||||
]]
|
||||
});
|
||||
};
|
||||
|
||||
getOutput(tmp) {
|
||||
if(!tmp)
|
||||
return ["no data"];
|
||||
return [
|
||||
`Temperature: ${tmp.temperature.toFixed(2)} °C (feels like ${this.calculateHeatIndexCelcius(tmp.temperature, tmp.humidity).toFixed(2)} °C)`,
|
||||
`Dewpoint: ${this.calculateDewPointCelcius(tmp.temperature, tmp.humidity).toFixed(2)} °C`,
|
||||
`Humidity: ${tmp.humidity.toFixed(2)}%`,
|
||||
`Pressure: ${tmp.pressure.toFixed(2)} hPa`,
|
||||
`Gas: ${tmp.gas} KOhms`,
|
||||
`Altitude: ~${tmp.altitude.toFixed(2)} m`,
|
||||
`Light: ${tmp.light}`,
|
||||
``,
|
||||
`Timestamp: ${tmp.date}`
|
||||
];
|
||||
};
|
||||
|
||||
convertToCSV(legend, objArray) {
|
||||
const array = typeof objArray != 'object' ? JSON.parse(objArray) : objArray;
|
||||
let str = legend.join(",") + "\n";
|
||||
for(let i = 0; i < array.length; i++) {
|
||||
let line = '';
|
||||
for(let index in array[i]) {
|
||||
if(line != '')
|
||||
line += ','
|
||||
line += array[i][index];
|
||||
}
|
||||
str += line + '\n';
|
||||
}
|
||||
return str;
|
||||
};
|
||||
};
|
4
src/inc/sql.mjs
Normal file
4
src/inc/sql.mjs
Normal file
|
@ -0,0 +1,4 @@
|
|||
import mariadb from "mariadb";
|
||||
import cfg from "../../config.json";
|
||||
|
||||
export default mariadb.createPool(cfg.sql);
|
81
src/index.mjs
Normal file
81
src/index.mjs
Normal file
|
@ -0,0 +1,81 @@
|
|||
import slimbot from "slimbot";
|
||||
import net from "net";
|
||||
import cfg from "../config.json";
|
||||
import sql from "./inc/sql.mjs";
|
||||
import graph from "./inc/graph.mjs";
|
||||
import lib from "./inc/lib.mjs";
|
||||
|
||||
(async () => {
|
||||
const bot = new slimbot(cfg.bot[0].token);
|
||||
const server = net.createServer();
|
||||
let tmp;
|
||||
|
||||
server.on('connection', socket => {
|
||||
socket.setEncoding('utf8');
|
||||
console.log(`new connection: (${socket.remoteFamily}) ${socket.remoteAddress}:${socket.remotePort}`);
|
||||
let tt = null;
|
||||
let data = "";
|
||||
let model = "";
|
||||
|
||||
socket.on('data', d => {
|
||||
data += d;
|
||||
tt = null;
|
||||
tt = setTimeout(() => {
|
||||
if(data.length <= 5)
|
||||
return data = "";
|
||||
try {
|
||||
console.log("data", data.trimEnd());
|
||||
data = JSON.parse(data);
|
||||
if(data?.type === "ident")
|
||||
model = data.model;
|
||||
|
||||
if(data?.data && model) {
|
||||
tmp = { ...data.data, date: new Date().toLocaleString("de-DE") };
|
||||
sql.query(`insert into weather_data_${model} (temperature, humidity, pressure, gas, light) values (?, ?, ?, ?, ?)`, [
|
||||
tmp.temperature,
|
||||
tmp.humidity,
|
||||
tmp.pressure,
|
||||
tmp.gas,
|
||||
tmp.light
|
||||
]).then(() => {});
|
||||
}
|
||||
} catch(err) {
|
||||
console.error(err);
|
||||
}
|
||||
data = "";
|
||||
return;
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
|
||||
bot.on("message", async e => {
|
||||
if(!e.text || !tmp)
|
||||
return false;
|
||||
if(!e.text.startsWith("/temp@keindevbot"))
|
||||
return false;
|
||||
|
||||
bot.sendMessage(e.chat.id, lib.getOutput(tmp).join("\n"), {
|
||||
reply_to_message_id: e.message_id,
|
||||
reply_markup: lib.getInline()
|
||||
});
|
||||
});
|
||||
|
||||
bot.on("callback_query", async q => {
|
||||
if(!q.data)
|
||||
return false;
|
||||
let link = await graph(q.data.substring(2));
|
||||
let output = lib.getOutput(tmp);
|
||||
|
||||
if(link.success)
|
||||
output[output.length - 1] += `[](${link.link})`;
|
||||
|
||||
bot.editMessageText(q.message.chat.id, q.message.message_id, output.join("\n"), {
|
||||
parse_mode: "markdown",
|
||||
reply_markup: lib.getInline()
|
||||
});
|
||||
});
|
||||
|
||||
server.listen(3000);
|
||||
bot.startPolling();
|
||||
|
||||
})();
|
Loading…
Reference in New Issue
Block a user