网页访问单片机设备---基于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>
相关推荐
yaoxin52112320 小时前
430. Java 日期时间 API - 时间计算 Temporal 包
java·前端·python
ldmd28420 小时前
Typescript 入门篇-3
javascript·typescript·notepad++
Cobyte21 小时前
18.【SolidJS】 采用 template 内容模板元素创建 DOM 元素
前端·javascript·vue.js
山峰哥21 小时前
VB事件驱动编程实战:从零到一搭建完整管理系统
前端·数据库·性能优化·深度优先·vb
LucianaiB21 小时前
Swarm管理面板的多项目配置策略与模型别名机制的效率分析
java·服务器·前端
IT_陈寒21 小时前
Redis缓存雪崩,原来我一直在用错误的方式设置过期时间
前端·人工智能·后端
怕浪猫21 小时前
Electron 开发实战(十二):安全性最佳实践|彻底杜绝漏洞、代码执行与数据泄露
前端·javascript·electron
wgc2k21 小时前
NestJS基础-7: 官方 CLI 完整使用指南
前端
AI_零食21 小时前
HarmonyOS-鸿蒙原生 ArkTS 布局系统:width(‘100%‘) 的本质与 padding 陷阱
前端·学习·华为·harmonyos·鸿蒙
英俊潇洒美少年21 小时前
React18 flushSync 完整深度解析
前端·react