网页访问单片机设备---基于mqtt

  1. 将这个html文件放到云服务器, 然后通过连接访问这个html文件, 就可以打开界面(本地测试直接使用浏览器打开)

2.由于网页端无法使用1883访问mqtt服务器, 只能使用8083端口, 因此需要让mqtt broker支持

3.理论条件完全打通, 只需要订阅单片机设备的发布订阅主题, 那么就可以通过这个主题发送不容的命令, 读取/写入配置(客户不需要下载app, 手机/电脑可以同时访问, 简直完美)

电脑端展示

手机端展示

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8" />
    <title>MQTT 收发调试面板</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: "Microsoft Yahei", sans-serif;
        }
        body {
            background-color: #f4f5f7;
            padding: 20px;
            max-width: 700px;
            margin: 0 auto;
        }
        .box {
            background: #fff;
            padding: 20px;
            border-radius: 8px;
            margin-bottom: 15px;
            box-shadow: 0 1px 3px #ccc;
        }
        .status-on {
            color: #16a34a;
            font-weight: bold;
        }
        .status-off {
            color: #ef4444;
            font-weight: bold;
        }
        input, textarea {
            width: 100%;
            padding: 10px;
            margin: 8px 0;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 14px;
        }
        button {
            padding: 9px 16px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            margin: 4px;
        }
        .btn-blue {
            background: #2563eb;
            color: #fff;
        }
        .btn-green {
            background: #16a34a;
            color: #fff;
        }
        .btn-gray {
            background: #6b7280;
            color: #fff;
        }
        .log-area {
            height: 260px;
            background: #1e293b;
            color: #e2e8f0;
            padding: 12px;
            border-radius: 4px;
            overflow-y: auto;
            white-space: pre-wrap;
            font-size: 13px;
        }
    </style>
</head>
<body>
    <!-- MQTT连接配置 -->
    <div class="box">
        <h3>MQTT 连接配置 <span id="connState" class="status-off">未连接</span></h3>
        <input type="text" id="mqttIp" placeholder="服务器公网IP" value="" />
        <input type="number" id="mqttPort" placeholder="WebSocket端口 8083" value="8083" />
        <input type="text" id="mqttUser" placeholder="账号(无则空)" value="" />
        <input type="text" id="mqttPwd" placeholder="密码(无则空)" value="" />
        <div>
            <button class="btn-blue" onclick="mqttConnect()">连接服务器</button>
            <button class="btn-gray" onclick="mqttDisconnect()">断开连接</button>
        </div>
    </div>

    <!-- 订阅区域 -->
    <div class="box">
        <h3>订阅主题(接收设备数据)</h3>
        <input type="text" id="subTopic" placeholder="例:device/dtu01/reply" value="device/dtu01/reply" />
        <button class="btn-blue" onclick="subTopic()">订阅主题</button>
    </div>

    <!-- 发送区域 -->
    <div class="box">
        <h3>手动发送数据</h3>
        <input type="text" id="pubTopic" placeholder="发送主题" value="device/dtu01/config" />
        <textarea id="pubMsg" rows="4" placeholder="输入要下发的指令/JSON">{"heartbeat":60,"interval":30}</textarea>
        <button class="btn-green" onclick="sendMsg()">一键发送</button>
    </div>

    <!-- 日志区域 -->
    <div class="box">
        <h3>收发日志 <button class="btn-gray" onclick="clearLog()">清空日志</button></h3>
        <div class="log-area" id="logBox"></div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/mqtt@4.3.7/dist/mqtt.min.js"></script>
    <script>
        let client = null;
        const logBox = document.getElementById('logBox');
        const connState = document.getElementById('connState');

        // 打印日志
        function log(text) {
            const time = new Date().toLocaleTimeString();
            logBox.innerText += `[${time}] ${text}\n`;
            logBox.scrollTop = logBox.scrollHeight;
        }

        // 连接MQTT
        function mqttConnect() {
            const ip = document.getElementById('mqttIp').value.trim();
            const port = document.getElementById('mqttPort').value;
            const user = document.getElementById('mqttUser').value;
            const pwd = document.getElementById('mqttPwd').value;

            if (!ip) {
                alert("请填写服务器IP");
                return;
            }

            const wsUrl = `ws://${ip}:${port}/mqtt`;
            const opts = {
                username: user || undefined,
                password: pwd || undefined,
                clientId: "web_send_" + Date.now()
            };

            client = mqtt.connect(wsUrl, opts);

            client.on('connect', () => {
                connState.innerText = "已连接";
                connState.className = "status-on";
                log("✅ MQTT 服务器连接成功");
            });

            client.on('error', (err) => {
                log(`❌ 连接失败:${err.message}`);
            });

            client.on('close', () => {
                connState.innerText = "已断开";
                connState.className = "status-off";
                log("🔌 MQTT 连接断开");
            });

            // 接收订阅消息
            client.on('message', (topic, payload) => {
                const data = payload.toString();
                log(`📥 接收【${topic}】: ${data}`);
            });
        }

        // 订阅主题
        function subTopic() {
            if (!client || !client.connected) {
                alert("请先连接MQTT服务器");
                return;
            }
            const topic = document.getElementById('subTopic').value.trim();
            client.subscribe(topic);
            log(`📌 已订阅主题:${topic}`);
        }

        // 发布发送数据
        function sendMsg() {
            if (!client || !client.connected) {
                alert("请先连接MQTT服务器");
                return;
            }
            const topic = document.getElementById('pubTopic').value.trim();
            const msg = document.getElementById('pubMsg').value;
            client.publish(topic, msg);
            log(`📤 发送【${topic}】: ${msg}`);
        }

        // 断开连接
        function mqttDisconnect() {
            if (client) client.end();
        }

        // 清空日志
        function clearLog() {
            logBox.innerText = "";
        }
    </script>
</body>
</html>
</html>
相关推荐
程序员黑豆4 小时前
Java类型推断完全指南:从var到菱形运算符,掌握使用限制与最佳实践
java·前端·ai编程
To_OC5 小时前
踩了个 TS 的坑之后,我终于把 type 和 interface 掰明白了
前端·react.js·typescript
GreenTea5 小时前
深度解读 Anthropic 多智能体报告:更强的模型 ≠ 更好的协调
前端·后端·算法
浮生望5 小时前
前端API工程化:用 Mock 数据与 Axios 配置实现独立于后端的并行开发
前端
万少5 小时前
给 DeepSeek Harness 装个"应用商店":一条命令,595 个插件随你逛
前端·javascript·后端
波波0076 小时前
C# 15 重磅新特性: 带标签 break 与 continue:重新定义嵌套循环控制流
服务器·前端·c#
Brown.alexis7 小时前
es6知识点1-自备使用
前端·ecmascript·es6
小爬的老粉丝7 小时前
JavaScript 纯前端预览 WPS:先识别容器,再路由解析器
前端·javascript·wps
计算机魔术师8 小时前
新兴多智能体系统的模式与问题
前端
用户059540174469 小时前
AI Agent 上下文污染踩坑实录:用 pytest + Redis 揪出 3 类记忆串号 bug,排查 6 小时
前端·css