↩️ Назад

Категории

sensors.php админка для управления метаданными датчиков

23.11.2025 | коды из категории: IOT умный дом

про sensors.php

обновлено 15.02.2026 добавил возможность выбирать топики для построения графиков и сбор исторических денных

🛠️ sensors.php — Управление метаданными датчиков

Этот файл отвечает за настройку описательной информации о ваших IoT-устройствах: как они называются, в какой комнате находятся, к какой группе относятся и какую иконку показывать в интерфейсе.

Данные хранятся в таблице sensor_info и сопоставляются с топиками из sensor_data. Например:

Интерфейс позволяет:

Это упрощает построение пользовательского интерфейса: вы оперируете не «сырыми» MQTT-топиками, а понятными именами и категориями.

<?php
session_start();

// Защита по IP — раскомментируй, если нужна
// $allowed_ips = ['192.168.0.1', '127.0.0.1'];
// if (!in_array($_SERVER['REMOTE_ADDR'], $allowed_ips)) {
//     header('HTTP/1.1 403 Forbidden');
//     die("Доступ запрещён");
// }

// Авторизация
$valid_username = 'iot_user';
$valid_password = '123456';

$error = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    if (isset($_POST['username'])) {
        // Вход
        $username = $_POST['username'] ?? '';
        $password = $_POST['password'] ?? '';
        if ($username === $valid_username && $password === $valid_password) {
            $_SESSION['iot_admin'] = true;
        } else {
            $error = "Неверный логин или пароль";
        }
    } elseif (isset($_POST['save'])) {
        // Сохранение датчика
        $topic = trim($_POST['topic'] ?? '');
        $name = $_POST['name'] ?? '';
        $room = $_POST['room'] ?? '';
        $group = $_POST['group_name'] ?? '';
        $icon = $_POST['icon'] ?? '';
        $save_history = !empty($_POST['save_history']) ? 1 : 0;

        if (!empty($topic)) {
            try {
                $pdo = new PDO("mysql:host=127.0.0.1;dbname=iot_db;charset=utf8mb4", "iot_user", "123456");
                $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

                $stmt = $pdo->prepare("
                    INSERT INTO sensor_info (topic, name, room, group_name, icon, save_history)
                    VALUES (?, ?, ?, ?, ?, ?)
                    ON DUPLICATE KEY UPDATE
                        name = VALUES(name),
                        room = VALUES(room),
                        group_name = VALUES(group_name),
                        icon = VALUES(icon),
                        save_history = VALUES(save_history)
                ");
                $stmt->execute([$topic, $name, $room, $group, $icon, $save_history]);
            } catch (Exception $e) {
                die("Ошибка сохранения: " . $e->getMessage());
            }
        }
    }
}

if (!isset($_SESSION['iot_admin'])) {
    ?>
    <!DOCTYPE html>
    <html lang="ru">
    <head><meta charset="UTF-8"><title>🔐 Вход</title></head>
    <body>
        <h2>🔐 Авторизация</h2>
        <?php if ($error): ?><p style="color:red"><?= $error ?></p><?php endif; ?>
        <form method="post">
            <label>Логин<br><input type="text" name="username" required></label><br>
            <label>Пароль<br><input type="password" name="password" required></label><br>
            <button type="submit">Войти</button>
        </form>
    </body>
    </html>
    <?php
    exit;
}
?>

<?php
// Подключение к БД
try {
    $pdo = new PDO("mysql:host=127.0.0.1;dbname=iot_db;charset=utf8mb4", "iot_user", "123456");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Получаем список всех топиков из sensor_data
    $stmt = $pdo->query("SELECT DISTINCT topic FROM sensor_data");
    $topics = $stmt->fetchAll(PDO::FETCH_COLUMN, 0);

    // Получаем текущие данные из sensor_info
    $stmt = $pdo->query("SELECT * FROM sensor_info");
    $info = $stmt->fetchAll(PDO::FETCH_ASSOC);
    $infoMap = [];
    foreach ($info as $row) {
        $infoMap[$row['topic']] = $row;
    }

} catch (PDOException $e) {
    die("Ошибка подключения: " . $e->getMessage());
}

// Удаление
if (isset($_GET['delete'])) {
    $topic_to_delete = $_GET['delete'];

    $pdo->prepare("DELETE FROM sensor_info WHERE topic = ?")->execute([$topic_to_delete]);
    $pdo->prepare("DELETE FROM sensor_data WHERE topic = ?")->execute([$topic_to_delete]);
    $pdo->prepare("DELETE FROM sensor_history WHERE topic = ?")->execute([$topic_to_delete]);

    header("Location: sensors.php");
    exit;
}
?>

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>🛠️ Админка IoT</title>
    <style>
        :root {
            --bg-main: #1e1e2e;
            --bg-panel: #252536;
            --bg-input: #2d2d3d;
            --text: #e0e0ff;
            --text-muted: #a0a0c0;
            --border: #3a3a4a;
            --accent: #6c63ff;
            --accent-hover: #5a52d5;
            --success: #4caf50;
            --error: #f44336;
            --warning: #ff9800;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            background-color: var(--bg-main);
            color: var(--text);
            padding: 20px;
            margin: 0;
        }

        h1, h2 {
            color: #ffffff;
            margin-bottom: 20px;
        }

        .form-box {
            background: var(--bg-panel);
            padding: 20px;
            border-radius: 10px;
            margin-bottom: 30px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
            border: 1px solid var(--border);
        }

        label {
            display: block;
            margin-top: 14px;
            color: #d0d0e8;
            font-size: 0.95em;
        }

        small {
            display: block;
            color: var(--text-muted);
            font-size: 0.85em;
            margin-top: 4px;
        }

        input, select, textarea, datalist {
            width: 100%;
            padding: 10px;
            margin-top: 6px;
            background: var(--bg-input);
            border: 1px solid var(--border);
            border-radius: 6px;
            color: var(--text);
            font-size: 1em;
        }

        input[type="checkbox"] {
            width: auto;
            margin-right: 8px;
        }

        button, input[type="submit"] {
            padding: 10px 20px;
            background: var(--accent);
            color: white;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-weight: 600;
            transition: background 0.2s;
        }

        button:hover, input[type="submit"]:hover {
            background: var(--accent-hover);
        }

        table {
            width: 100%;
            border-collapse: collapse;
            margin-top: 20px;
            background: var(--bg-panel);
            border: 1px solid var(--border);
            border-radius: 8px;
            overflow: hidden;
        }

        th, td {
            padding: 12px;
            border: 1px solid var(--border);
            text-align: left;
            color: var(--text);
        }

        th {
            background: #2a2a3a;
            font-weight: 600;
        }

        .history-yes { color: var(--success); }
        .history-no { color: var(--error); }

        .actions a {
            margin-right: 12px;
            text-decoration: none;
            color: var(--accent);
        }

        .actions a:hover {
            text-decoration: underline;
        }
    </style>
</head>
<body>

<h1>🛠️ Админка: Редактирование датчиков</h1>

<!-- Форма добавления/редактирования -->
<form method="post">
    <label>Топик:</label><br>
    <input type="text" name="topic" required list="topics"><br><br>

    <label>Имя датчика:</label><br>
    <input type="text" name="name"><br><br>

    <label>Комната:</label><br>
    <input type="text" name="room"><br><br>

    <label>Группа (например: Дом, Дача):</label><br>
    <input type="text" name="group_name"><br><br>

    <label>Иконка (например: 🌡️, 🚪, 🌿):</label><br>
    <input type="text" name="icon"><br><br>

    <label>
        <input type="checkbox" name="save_history" value="1">
        Сохранять историю (график)
    </label><br><br>

    <input type="submit" name="save" value="Сохранить">
</form>

<datalist id="topics">
    <?php foreach ($topics as $t): ?>
        <option value="<?= htmlspecialchars($t) ?>">
    <?php endforeach; ?>
</datalist>

<!-- Таблица датчиков -->
<h2>📊 Все датчики</h2>
<table>
    <thead>
        <tr>
            <th>Топик</th>
            <th>Имя</th>
            <th>Комната</th>
            <th>Группа</th>
            <th>Иконка</th>
            <th>График?</th>
            <th>Управление</th>
        </tr>
    </thead>
    <tbody>
        <?php foreach ($topics as $topic):
            $entry = $infoMap[$topic] ?? [];
            $save_history = ($entry['save_history'] ?? 0) == 1;
        ?>
            <tr>
                <td><?= htmlspecialchars($topic) ?></td>
                <td><?= htmlspecialchars($entry['name'] ?? '') ?></td>
                <td><?= htmlspecialchars($entry['room'] ?? '') ?></td>
                <td><?= htmlspecialchars($entry['group_name'] ?? '') ?></td>
                <td><?= htmlspecialchars($entry['icon'] ?? '') ?></td>
                <td class="<?= $save_history ? 'history-yes' : 'history-no' ?>">
                    <?= $save_history ? '✅ Да' : '❌ Нет' ?>
                </td>
                <td>
                    <a href="#" onclick="fillForm(
                        '<?= addslashes($topic) ?>',
                        '<?= addslashes($entry['name'] ?? '') ?>',
                        '<?= addslashes($entry['room'] ?? '') ?>',
                        '<?= addslashes($entry['group_name'] ?? '') ?>',
                        '<?= addslashes($entry['icon'] ?? '') ?>',
                        <?= $save_history ? 'true' : 'false' ?>
                    )">✏️ Ред.</a>
                    <a href="?delete=<?= urlencode($topic) ?>" onclick="return confirm('Удалить?')">🗑️ Удалить</a>
                </td>
            </tr>
        <?php endforeach; ?>
    </tbody>
</table>

<script>
function fillForm(topic, name, room, group, icon, saveHistory) {
    document.querySelector("[name='topic']").value = topic;
    document.querySelector("[name='name']").value = name;
    document.querySelector("[name='room']").value = room;
    document.querySelector("[name='group_name']").value = group;
    document.querySelector("[name='icon']").value = icon;
    document.querySelector("[name='save_history']").checked = saveHistory;
}
</script>

<form method="post" action="/admin/logout.php" style="margin-top: 30px;">
    <button type="submit">🚪 Выйти</button>
</form>

</body>
</html>



Категории:

Категории

Комментарии

Пока нет комментариев. Будьте первым!

Оставить комментарий

← Назад к списку

Посетителей сегодня: 0
о блоге | карта блога

© Digital Specialist | Не являемся сотрудниками Google, Яндекса и NASA