网页访问单片机设备---基于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>
相关推荐
前端一小卒1 小时前
我用 Claude Code 的 Superpowers 技能链写了个服务,部署前差点把服务器搞炸
前端·javascript·后端
滑雪的企鹅.3 小时前
HTML头部元信息避坑指南大纲
前端·html
一拳不是超人3 小时前
老婆天天吵吵要买塔罗牌,我直接用 AI 2 小时写了个在线塔罗牌
前端·ai编程
excel4 小时前
如何解决 Nuxt DevTools 中关于 unstorage 包的报错
前端
Rust研习社4 小时前
使用 Axum 构建高性能异步 Web 服务
开发语言·前端·网络·后端·http·rust
C澒5 小时前
AI 生码 - API2Code:接口智能匹配与 API 自动化生码全链路设计
前端·低代码·ai编程
浔川python社5 小时前
HTML头部元信息避坑指南技术文章大纲
前端·html
IT_陈寒5 小时前
SpringBoot配置加载顺序把我坑惨了
前端·人工智能·后端
kyriewen5 小时前
Next.js部署:从本地跑得欢,到线上飞得稳
前端·react.js·next.js