164 lines
6.3 KiB
JavaScript

const express = require('express');
const router = express.Router();
const db = require('../../db');
const { isAuthenticated, hasRole } = require('../../middleware/authMiddleware');
const { requireModule } = require('../../middleware/licenseMiddleware');
// Get all cameras - Protected by Module License
router.get('/', requireModule('monitoring'), async (req, res) => {
try {
const [rows] = await db.query('SELECT * FROM camera_settings ORDER BY display_order ASC, created_at DESC');
res.json(rows);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Reorder cameras (Admin only)
router.put('/reorder', hasRole('admin'), async (req, res) => {
const { cameras } = req.body; // Array of { id, display_order } or just ordered IDs
if (!Array.isArray(cameras)) {
return res.status(400).json({ error: 'Invalid data format' });
}
try {
// Use a transaction for safety
await db.query('START TRANSACTION');
for (let i = 0; i < cameras.length; i++) {
const cam = cameras[i];
// If receiving array of IDs, use index as order
const id = typeof cam === 'object' ? cam.id : cam;
const order = i;
await db.query('UPDATE camera_settings SET display_order = ? WHERE id = ?', [order, id]);
}
await db.query('COMMIT');
res.json({ message: 'Cameras reordered' });
} catch (err) {
await db.query('ROLLBACK');
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Get single camera
router.get('/:id', async (req, res) => {
try {
const [rows] = await db.query('SELECT * FROM camera_settings WHERE id = ?', [req.params.id]);
if (rows.length === 0) return res.status(404).json({ error: 'Camera not found' });
res.json(rows[0]);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Add camera (Admin only)
router.post('/', hasRole('admin'), async (req, res) => {
const { name, ip_address, port, username, password, stream_path, transport_mode, rtsp_encoding, quality } = req.body;
try {
const sql = `INSERT INTO camera_settings (name, ip_address, port, username, password, stream_path, transport_mode, rtsp_encoding, quality) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`;
const [result] = await db.query(sql, [name, ip_address, port || 554, username, password, stream_path || '/stream1', transport_mode || 'tcp', rtsp_encoding || false, quality || 'low']);
res.status(201).json({ message: 'Camera added', id: result.insertId });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Update camera (Admin only)
router.put('/:id', hasRole('admin'), async (req, res) => {
const { name, ip_address, port, username, password, stream_path, transport_mode, rtsp_encoding, quality } = req.body;
try {
const sql = `UPDATE camera_settings SET name=?, ip_address=?, port=?, username=?, password=?, stream_path=?, transport_mode=?, rtsp_encoding=?, quality=? WHERE id=?`;
const [result] = await db.query(sql, [name, ip_address, port, username, password, stream_path, transport_mode, rtsp_encoding, quality, req.params.id]);
if (result.affectedRows === 0) return res.status(404).json({ error: 'Camera not found' });
// Force stream reset (kick clients to trigger reconnect)
const streamRelay = req.app.get('streamRelay');
if (streamRelay) {
console.log(`Settings changed for camera ${req.params.id}, resetting stream...`);
streamRelay.resetStream(req.params.id);
}
res.json({ message: 'Camera updated' });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Toggle Stream Status (Admin only)
router.patch('/:id/status', hasRole('admin'), async (req, res) => {
const { is_active } = req.body;
try {
const [result] = await db.query('UPDATE camera_settings SET is_active = ? WHERE id = ?', [is_active, req.params.id]);
if (result.affectedRows === 0) return res.status(404).json({ error: 'Camera not found' });
const streamRelay = req.app.get('streamRelay');
if (streamRelay) {
// If disabled, stop stream. If enabled, reset (which stops and allows reconnect)
console.log(`Stream status changed for camera ${req.params.id} to ${is_active}`);
streamRelay.resetStream(req.params.id);
}
res.json({ message: `Stream ${is_active ? 'enabled' : 'disabled'}` });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
// Delete camera (Admin only)
router.delete('/:id', hasRole('admin'), async (req, res) => {
try {
const [result] = await db.query('DELETE FROM camera_settings WHERE id = ?', [req.params.id]);
if (result.affectedRows === 0) return res.status(404).json({ error: 'Camera not found' });
// Stop stream
const streamRelay = req.app.get('streamRelay');
if (streamRelay) {
streamRelay.stopStream(req.params.id);
}
res.json({ message: 'Camera deleted' });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Database error' });
}
});
const { exec } = require('child_process');
// ... existing routes ...
// 7. Ping Test (Troubleshooting)
router.get('/:id/ping', isAuthenticated, async (req, res) => {
try {
const [rows] = await db.query('SELECT ip_address FROM camera_settings WHERE id = ?', [req.params.id]);
if (rows.length === 0) return res.status(404).json({ error: 'Camera not found' });
const ip = rows[0].ip_address;
// Simple ping command
const platform = process.platform;
const cmd = platform === 'win32' ? `ping -n 1 ${ip}` : `ping -c 1 ${ip}`;
exec(cmd, (error, stdout, stderr) => {
res.json({
ip,
success: !error,
output: stdout,
error: stderr
});
});
} catch (err) {
res.status(500).json({ error: 'Ping failed' });
}
});
module.exports = router;