feat: implement sensor connection and health check endpoints

This commit is contained in:
Giuseppe Raffa
2026-04-14 17:05:24 +02:00
parent c478f5c13c
commit d79c12b6e9
4 changed files with 129 additions and 1 deletions

View File

@@ -1,9 +1,31 @@
const express = require('express');
const crypto = require('crypto');
const app = express();
const db = require('./store/db')
app.use(express.json());
app.get('/', (req, res) => {});
// DATABASE POSTGRESQL
app.get('/', (req, res) => {
res.redirect('/health');
});
app.get('/health', (req, res) => {
const sensorsDB = db.checkConnection('sensors');
const dataDB = db.checkConnection('data');
res.json({
status: 'ok',
sensorsDB: sensorsDB,
dataDB: dataDB
});
});
app.use('/connect', require('./routes/connect'));
app.use('/sensors', require('./routes/sensors'));
app.listen(3000, '0.0.0.0', () => {
console.log(`Realtime started`);

View File

@@ -0,0 +1,35 @@
const router = require('express').Router();
const db = require('../store/db');
const crypto = require('crypto');
router.post('/connect/new', async (req, res) => {
const { name, code } = req.body;
if (!name || !code) {
return res.status(400).json({ error: 'name and code are required' });
}
if (code.length < 6) {
return res.status(400).json({ error: 'code must be at least 6 characters' });
}
const salt = crypto.randomBytes(16).toString('hex');
const hash = crypto.scryptSync(code, salt, 64).toString('hex');
const codeHash = `${salt}:${hash}`;
try {
await db.query('sensors',
'INSERT INTO sensors (name, code_hash) VALUES ($1, $2)',
[name, codeHash]
);
res.status(201).json({ status: 'ok' });
} catch (err) {
if (err.code === '23505') {
return res.status(409).json({ error: 'name already exists' });
}
console.error('Error creating sensor', err);
res.status(500).json({ error: 'internal server error' });
}
});
module.exports = router;

View File

@@ -0,0 +1,14 @@
const router = require('express').Router();
const db = require('../store/db');
router.get('/sensors', async (req, res) => {
try {
const result = await db.query('SELECT id, name FROM sensors', [], 'sensors');
res.json(result.rows);
} catch (err) {
console.error('Error fetching sensors', err);
res.status(500).json({ error: 'internal server error' });
}
});
module.exports = router;

57
realtime/src/store/db.js Normal file
View File

@@ -0,0 +1,57 @@
const { Pool } = require('pg');
const { get } = require('../../../api/src/routes/params.sensor');
const pool = new Pool({
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
host: process.env.DB_HOST,
port: process.env.DB_PORT,
max: 10,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 5000,
})
const dbs = {
data: { name: process.env.DATA_DB },
sensors: { name: process.env.SENSOR_DB }
}
function getPool(db) {
const dbConfig = dbs[db];
if (!dbConfig) throw new Error(`Database ${db} not configured`);
return new Pool({ ...pool.options, database: dbConfig.name });
}
async function checkConnection(db) {
try {
await getPool(db).query('SELECT NOW()');
return true;
} catch (err) {
console.error(`Error connecting to ${db} database`, err);
return false;
}
}
async function query(db, text, params) {
const pool = getPool(db);
return pool.query(text, params);
}
async function init() {
try {
await query('sensors', `
CREATE TABLE IF NOT EXISTS sensors (
id SERIAL PRIMARY KEY,
name VARCHAR(255) UNIQUE NOT NULL,
code_hash TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
`);
} catch (err) {
console.error('Error creating sensors table', err);
}
}
init();
module.exports = { checkConnection, query };