找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
广告投放联系QQ68610888广告投放联系QQ68610888
广告投放联系QQ68610888广告投放联系QQ68610888
查看: 675|回复: 7

我用ai写了openwrt的luci的大屏幕信息界面,大家看咋样

[复制链接]
发表于 2026-6-17 17:13 | 显示全部楼层 |阅读模式
本帖最后由 676220229 于 2026-6-20 23:51 编辑
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>OpenWrt 系统监控面板</title>
  7.     <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  8.     <style>
  9.         * {
  10.             margin: 0;
  11.             padding: 0;
  12.             box-sizing: border-box;
  13.             font-family: "Microsoft YaHei", sans-serif;
  14.         }

  15.         /* 彩色动态渐变背景 */
  16.         body {
  17.             min-height: 100vh;
  18.             background: linear-gradient(-45deg, #0072ff, #00c6ff, #3a1c71, #d76d77);
  19.             background-size: 400% 400%;
  20.             animation: gradientBg 15s ease infinite;
  21.             display: flex;
  22.             flex-direction: column;
  23.             align-items: center;
  24.             padding: 40px 20px;
  25.         }

  26.         @keyframes gradientBg {
  27.             0% { background-position: 0% 50%; }
  28.             50% { background-position: 100% 50%; }
  29.             100% { background-position: 0% 50%; }
  30.         }

  31.         .container {
  32.             width: 100%;
  33.             max-width: 1200px;
  34.         }

  35.         .header-card {
  36.             background: rgba(255, 255, 255, 0.15);
  37.             backdrop-filter: blur(12px);
  38.             border-radius: 20px;
  39.             padding: 30px;
  40.             text-align: center;
  41.             color: #fff;
  42.             box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
  43.             margin-bottom: 30px;
  44.             transition: all 0.3s ease;
  45.         }

  46.         .header-card:hover {
  47.             transform: translateY(-5px);
  48.             box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
  49.         }

  50.         #clock {
  51.             font-size: 48px;
  52.             font-weight: bold;
  53.             margin: 10px 0;
  54.             letter-spacing: 3px;
  55.         }

  56.         .grid-box {
  57.             display: grid;
  58.             grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  59.             gap: 24px;
  60.         }

  61.         .data-card {
  62.             background: rgba(255, 255, 255, 0.15);
  63.             backdrop-filter: blur(12px);
  64.             border-radius: 20px;
  65.             padding: 28px;
  66.             color: #fff;
  67.             box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
  68.             transition: all 0.3s ease;
  69.         }

  70.         .data-card:hover {
  71.             transform: translateY(-8px);
  72.             box-shadow: 0 15px 45px rgba(0, 0, 0, 0.22);
  73.         }

  74.         .card-title {
  75.             font-size: 16px;
  76.             opacity: 0.9;
  77.             margin-bottom: 16px;
  78.         }

  79.         .card-value {
  80.             font-size: 36px;
  81.             font-weight: 700;
  82.             margin-bottom: 12px;
  83.         }

  84.         .chart-wrap {
  85.             width: 100%;
  86.             height: 160px;
  87.         }

  88.         .ip-text {
  89.             word-break: break-all;
  90.             font-size: 22px;
  91.         }

  92.         .speed-tag {
  93.             display: inline-block;
  94.             padding: 6px 14px;
  95.             border-radius: 30px;
  96.             background: rgba(255,255,255,0.2);
  97.             margin-right: 10px;
  98.             margin-top: 8px;
  99.         }
  100.     </style>
  101. </head>
  102. <body>
  103.     <div class="container">
  104.         <!-- 顶部时钟卡片 -->
  105.         <div class="header-card">
  106.             <h1>OpenWrt 系统实时监控面板</h1>
  107.             <div id="clock">00:00:00</div>
  108.             <div id="date"></div>
  109.         </div>

  110.         <div class="grid-box">
  111.             <!-- CPU使用率 -->
  112.             <div class="data-card">
  113.                 <div class="card-title">💻 CPU 使用率</div>
  114.                 <div class="chart-wrap">
  115.                     <canvas id="cpuChart"></canvas>
  116.                 </div>
  117.                 <div class="card-value" id="cpuRate">0%</div>
  118.             </div>

  119.             <!-- 内存使用率 -->
  120.             <div class="data-card">
  121.                 <div class="card-title">🧠 内存使用率</div>
  122.                 <div class="chart-wrap">
  123.                     <canvas id="memChart"></canvas>
  124.                 </div>
  125.                 <div class="card-value" id="memRate">0%</div>
  126.             </div>

  127.             <!-- 实时上下行网速 -->
  128.             <div class="data-card">
  129.                 <div class="card-title">📶 实时网络速率</div>
  130.                 <div class="speed-tag">⬆ 上传:<span id="uploadSpeed">0 KB/s</span></div>
  131.                 <div class="speed-tag">⬇ 下载:<span id="downloadSpeed">0 KB/s</span></div>
  132.             </div>

  133.             <!-- 公网IP -->
  134.             <div class="data-card">
  135.                 <div class="card-title">🌐 当前公网 IP</div>
  136.                 <div class="ip-text" id="publicIp">获取中...</div>
  137.             </div>
  138.         </div>
  139.     </div>

  140.     <script>
  141.         // 1. 实时时钟
  142.         function updateClock() {
  143.             const now = new Date();
  144.             const timeStr = now.toLocaleTimeString('zh-CN', {hour12: false});
  145.             const dateStr = now.toLocaleDateString('zh-CN', {weekday:'long',year:'numeric',month:'long',day:'numeric'});
  146.             document.getElementById('clock').innerText = timeStr;
  147.             document.getElementById('date').innerText = dateStr;
  148.         }
  149.         setInterval(updateClock, 1000);
  150.         updateClock();

  151.         // 2. 初始化环形图表
  152.         const cpuCtx = document.getElementById('cpuChart').getContext('2d');
  153.         const memCtx = document.getElementById('memChart').getContext('2d');

  154.         const cpuChart = new Chart(cpuCtx, {
  155.             type: 'doughnut',
  156.             data: {
  157.                 datasets: [{
  158.                     data: [0, 100],
  159.                     backgroundColor: ['#00c6ff', 'rgba(255,255,255,0.1)'],
  160.                     borderWidth: 0
  161.                 }]
  162.             },
  163.             options: { cutout: '75%', responsive: true, maintainAspectRatio: false, plugins: {legend: {display:false}} }
  164.         });

  165.         const memChart = new Chart(memCtx, {
  166.             type: 'doughnut',
  167.             data: {
  168.                 datasets: [{
  169.                     data: [0, 100],
  170.                     backgroundColor: ['#ff7675', 'rgba(255,255,255,0.1)'],
  171.                     borderWidth: 0
  172.                 }]
  173.             },
  174.             options: { cutout: '75%', responsive: true, maintainAspectRatio: false, plugins: {legend: {display:false}} }
  175.         });

  176.         // 3. 读取OpenWrt系统数据
  177.         let lastRx = 0, lastTx = 0;
  178.         const netDev = 'eth0'; // 改成你的WAN网卡,一般eth0/pppoe-wan

  179.         async function getSystemData() {
  180.             try {
  181.                 // CPU 负载
  182.                 const resCpu = await fetch('/proc/loadavg');
  183.                 const loadText = await resCpu.text();
  184.                 const cpuLoad = parseFloat(loadText.split(' ')[0]) * 100;
  185.                 const cpuPercent = Math.min(Math.round(cpuLoad), 100);
  186.                 cpuChart.data.datasets[0].data = [cpuPercent, 100 - cpuPercent];
  187.                 cpuChart.update();
  188.                 document.getElementById('cpuRate').innerText = cpuPercent + '%';

  189.                 // 内存
  190.                 const resMem = await fetch('/proc/meminfo');
  191.                 const memText = await resMem.text();
  192.                 const memTotal = parseInt(memText.match(/MemTotal:\s+(\d+)/)[1]);
  193.                 const memFree = parseInt(memText.match(/MemFree:\s+(\d+)/)[1]);
  194.                 const memUsed = memTotal - memFree;
  195.                 const memPercent = Math.round(memUsed / memTotal * 100);
  196.                 memChart.data.datasets[0].data = [memPercent, 100 - memPercent];
  197.                 memChart.update();
  198.                 document.getElementById('memRate').innerText = memPercent + '%';

  199.                 // 网卡流量计算网速
  200.                 const resNet = await fetch(`/proc/net/dev`);
  201.                 const netText = await resNet.text();
  202.                 const match = netText.match(new RegExp(`${netDev}:\\s*(\\d+)\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+(\\d+)`));
  203.                 if(match){
  204.                     const rx = parseInt(match[1]);
  205.                     const tx = parseInt(match[2]);
  206.                     if(lastRx !== 0){
  207.                         const down = ((rx - lastRx) / 1024).toFixed(2);
  208.                         const up = ((tx - lastTx) / 1024).toFixed(2);
  209.                         document.getElementById('downloadSpeed').innerText = `${down} KB/s`;
  210.                         document.getElementById('uploadSpeed').innerText = `${up} KB/s`;
  211.                     }
  212.                     lastRx = rx;
  213.                     lastTx = tx;
  214.                 }

  215.                 // 获取公网IP
  216.                 if(!document.getElementById('publicIp').innerText.includes('.')){
  217.                     const ipRes = await fetch('https://api.ipify.org');
  218.                     const pubIp = await ipRes.text();
  219.                     document.getElementById('publicIp').innerText = pubIp;
  220.                 }
  221.             } catch (err) {
  222.                 console.log('数据读取异常:', err);
  223.             }
  224.         }

  225.         // 每1秒刷新一次数据
  226.         setInterval(getSystemData, 1000);
  227.         getSystemData();
  228.     </script>
  229. </body>
  230. </html>
复制代码


我用ai重写了openwrt的luci界面,大家看咋样,首页还需要显示哪些信息?对于家用来说,哪些信息足够用了?脱离原生 LuCI 布局,做独立 HTML 大屏首页,支持粒子背景、动态时钟、实时网速跑马灯、数据轮播动画、全屏毛玻璃,它有三种颜色,随背景可变。用的都是最基础的rgb色拼的没有用渲染。不浪费路由器的CPU。通过 AJAX 实时读取 OpenWrt 系统数据。

如如果大家喜欢,我就把源代码贴出来,自己打包成htm文件,用winscp上传到openwrt相应的位置。备份原有 index.html,将上面代码新建保存为 index.html,记住一定要备份,一定要备份。PPPoE 拨号改成:pppoe-wan
光猫桥接网口拨号:eth0、wan 根据自己网卡修改

请大家在应用之前建议先保存成HTML预览一遍,然后再用人工智能跑一遍,让他们嗯,提提意见。提提意见。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
只谈技术、莫论政事!(点击见详情) | 互相尊重、友善交流、切勿过度反应、玻璃心。胡乱输入灌水等操作将会被封禁ID。
 楼主| 发表于 2026-6-17 17:18 | 显示全部楼层
本帖最后由 676220229 于 2026-6-20 23:52 编辑

强烈建议大家谁有歪果的AI具的,让他把代码逐行再检查一遍。下面是阿里的千问优化过的代码,我觉得比起其他的智能,这版优化是应该是比较好的。

增加了动画和图标。
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>OpenWrt 系统监控面板</title>
  7.     <!-- 引入 Chart.js -->
  8.     <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  9.     <style>
  10.         * { margin: 0; padding: 0; box-sizing: border-box; font-family: "Microsoft YaHei", sans-serif; }

  11.         /* 动态渐变背景 */
  12.         body {
  13.             min-height: 100vh;
  14.             background: linear-gradient(-45deg, #0072ff, #00c6ff, #3a1c71, #d76d77);
  15.             background-size: 400% 400%;
  16.             animation: gradientBg 15s ease infinite;
  17.             display: flex;
  18.             flex-direction: column;
  19.             align-items: center;
  20.             padding: 40px 20px;
  21.             color: #fff;
  22.         }

  23.         @keyframes gradientBg {
  24.             0% { background-position: 0% 50%; }
  25.             50% { background-position: 100% 50%; }
  26.             100% { background-position: 0% 50%; }
  27.         }

  28.         .container { width: 100%; max-width: 1200px; }

  29.         /* 顶部时钟卡片 */
  30.         .header-card {
  31.             background: rgba(255, 255, 255, 0.15);
  32.             backdrop-filter: blur(12px);
  33.             border-radius: 20px;
  34.             padding: 30px;
  35.             text-align: center;
  36.             box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
  37.             margin-bottom: 30px;
  38.             transition: transform 0.3s ease;
  39.         }
  40.         .header-card:hover { transform: translateY(-5px); }

  41.         #clock { font-size: 48px; font-weight: bold; margin: 10px 0; letter-spacing: 3px; }
  42.         #date { font-size: 18px; opacity: 0.9; }

  43.         /* 网格布局 */
  44.         .grid-box {
  45.             display: grid;
  46.             grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  47.             gap: 24px;
  48.         }

  49.         .data-card {
  50.             background: rgba(255, 255, 255, 0.15);
  51.             backdrop-filter: blur(12px);
  52.             border-radius: 20px;
  53.             padding: 28px;
  54.             box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
  55.             transition: transform 0.3s ease;
  56.             display: flex;
  57.             flex-direction: column;
  58.             align-items: center;
  59.             text-align: center;
  60.         }
  61.         .data-card:hover { transform: translateY(-8px); }

  62.         .card-title { font-size: 16px; opacity: 0.9; margin-bottom: 15px; width: 100%; text-align: left; }
  63.         .card-value { font-size: 36px; font-weight: 700; margin: 10px 0; }
  64.         
  65.         .chart-wrap { width: 100%; height: 150px; position: relative; }

  66.         .ip-text { word-break: break-all; font-size: 20px; font-weight: bold; margin-top: 10px; }

  67.         .speed-group { display: flex; flex-direction: column; gap: 10px; width: 100%; margin-top: 10px; }
  68.         .speed-item { display: flex; justify-content: space-between; background: rgba(0,0,0,0.2); padding: 8px 15px; border-radius: 10px; font-size: 14px; }
  69.         .speed-val { font-weight: bold; font-family: monospace; }
  70.     </style>
  71. </head>
  72. <body>
  73.     <div class="container">
  74.         <!-- 顶部时钟 -->
  75.         <div class="header-card">
  76.             <h1>OpenWrt 实时监控</h1>
  77.             <div id="clock">00:00:00</div>
  78.             <div id="date">Loading...</div>
  79.         </div>

  80.         <div class="grid-box">
  81.             <!-- CPU -->
  82.             <div class="data-card">
  83.                 <div class="card-title">💻 CPU 使用率</div>
  84.                 <div class="chart-wrap"><canvas id="cpuChart"></canvas></div>
  85.                 <div class="card-value" id="cpuRate">0%</div>
  86.             </div>

  87.             <!-- 内存 -->
  88.             <div class="data-card">
  89.                 <div class="card-title">🧠 内存使用率</div>
  90.                 <div class="chart-wrap"><canvas id="memChart"></canvas></div>
  91.                 <div class="card-value" id="memRate">0%</div>
  92.             </div>

  93.             <!-- 网速 -->
  94.             <div class="data-card">
  95.                 <div class="card-title">📶 实时网速</div>
  96.                 <div class="speed-group">
  97.                     <div class="speed-item">
  98.                         <span>⬇ 下载</span>
  99.                         <span class="speed-val" id="downloadSpeed">0 KB/s</span>
  100.                     </div>
  101.                     <div class="speed-item">
  102.                         <span>⬆ 上传</span>
  103.                         <span class="speed-val" id="uploadSpeed">0 KB/s</span>
  104.                     </div>
  105.                 </div>
  106.             </div>

  107.             <!-- 公网IP -->
  108.             <div class="data-card">
  109.                 <div class="card-title">🌐 公网 IP</div>
  110.                 <div class="ip-text" id="publicIp">查询中...</div>
  111.             </div>
  112.         </div>
  113.     </div>

  114.     <script>
  115.         // 1. 时钟逻辑
  116.         function updateClock() {
  117.             const now = new Date();
  118.             document.getElementById('clock').innerText = now.toLocaleTimeString('zh-CN', {hour12: false});
  119.             document.getElementById('date').innerText = now.toLocaleDateString('zh-CN', {weekday:'long', year:'numeric', month:'long', day:'numeric'});
  120.         }
  121.         setInterval(updateClock, 1000);
  122.         updateClock();

  123.         // 2. 图表初始化
  124.         const createDoughnut = (ctx, color) => new Chart(ctx, {
  125.             type: 'doughnut',
  126.             data: { datasets: [{ data: [0, 100], backgroundColor: [color, 'rgba(255,255,255,0.1)'], borderWidth: 0, cutout: '75%' }] },
  127.             options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false }, tooltip: { enabled: false } } }
  128.         });

  129.         const cpuChart = createDoughnut(document.getElementById('cpuChart').getContext('2d'), '#00c6ff');
  130.         const memChart = createDoughnut(document.getElementById('memChart').getContext('2d'), '#ff7675');

  131.         // 3. 数据获取逻辑
  132.         let lastRx = 0, lastTx = 0, lastTime = Date.now();
  133.         const netInterface = 'eth0'; // ⚠️ 请根据实际情况修改网卡名,如 eth0, pppoe-wan 等

  134.         async function fetchData() {
  135.             try {
  136.                 // --- CPU 计算 (基于 /proc/stat 差值计算,比 loadavg 更准确) ---
  137.                 const statRes = await fetch('/proc/stat');
  138.                 const statText = await statRes.text();
  139.                 const cpuLine = statText.split('\n')[0]; // 获取第一行 cpu 总数据
  140.                 const cpuVals = cpuLine.split(/\s+/).slice(1).map(Number); // 提取数值
  141.                 const total = cpuVals.reduce((a, b) => a + b, 0);
  142.                 const idle = cpuVals[3];

  143.                 // 如果是第一次运行,只记录初始值
  144.                 if (window.prevTotal === undefined) {
  145.                     window.prevTotal = total;
  146.                     window.prevIdle = idle;
  147.                     return;
  148.                 }

  149.                 const diffTotal = total - window.prevTotal;
  150.                 const diffIdle = idle - window.prevIdle;
  151.                 const cpuPercent = Math.round(((diffTotal - diffIdle) / diffTotal) * 100) || 0;
  152.                
  153.                 window.prevTotal = total;
  154.                 window.prevIdle = idle;

  155.                 // 更新 CPU UI
  156.                 document.getElementById('cpuRate').innerText = cpuPercent + '%';
  157.                 cpuChart.data.datasets[0].data = [cpuPercent, 100 - cpuPercent];
  158.                 cpuChart.update('none'); // 'none' 模式避免动画卡顿


  159.                 // --- 内存计算 ---
  160.                 const memRes = await fetch('/proc/meminfo');
  161.                 const memText = await memRes.text();
  162.                 const memTotal = parseInt(memText.match(/MemTotal:\s+(\d+)/)[1]);
  163.                 const memFree = parseInt(memText.match(/MemFree:\s+(\d+)/)[1]);
  164.                 const buffers = parseInt(memText.match(/Buffers:\s+(\d+)/)[1] || 0);
  165.                 const cached = parseInt(memText.match(/Cached:\s+(\d+)/)[1] || 0);
  166.                 // 实际使用 = 总量 - 空闲 - 缓冲 - 缓存
  167.                 const memUsed = memTotal - memFree - buffers - cached;
  168.                 const memPercent = Math.round((memUsed / memTotal) * 100);

  169.                 document.getElementById('memRate').innerText = memPercent + '%';
  170.                 memChart.data.datasets[0].data = [memPercent, 100 - memPercent];
  171.                 memChart.update('none');

  172.                 // --- 网速计算 ---
  173.                 const netRes = await fetch('/proc/net/dev');
  174.                 const netText = await netRes.text();
  175.                 // 匹配网卡行,提取接收字节和发送字节
  176.                 const netMatch = netText.match(new RegExp(`${netInterface}:\\s*(\\d+)\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+\\d+\\s+(\\d+)`));
  177.                
  178.                 if (netMatch) {
  179.                     const rx = parseInt(netMatch[1]);
  180.                     const tx = parseInt(netMatch[2]);
  181.                     const now = Date.now();
  182.                     const timeDiff = (now - lastTime) / 1000; // 秒

  183.                     if (timeDiff > 0) {
  184.                         const downSpeed = ((rx - lastRx) / 1024 / timeDiff).toFixed(2);
  185.                         const upSpeed = ((tx - lastTx) / 1024 / timeDiff).toFixed(2);
  186.                         
  187.                         document.getElementById('downloadSpeed').innerText = `${downSpeed} KB/s`;
  188.                         document.getElementById('uploadSpeed').innerText = `${upSpeed} KB/s`;
  189.                     }
  190.                     lastRx = rx;
  191.                     lastTx = tx;
  192.                     lastTime = now;
  193.                 }

  194.                 // --- 公网 IP ---
  195.                 if (!document.getElementById('publicIp').innerText.includes('.')) {
  196.                     // 使用 ipify 获取公网 IP
  197.                     const ipRes = await fetch('https://api.ipify.org');
  198.                     const ip = await ipRes.text();
  199.                     document.getElementById('publicIp').innerText = ip;
  200.                 }

  201.             } catch (e) {
  202.                 console.error("获取数据失败:", e);
  203.             }
  204.         }

  205.         // 每秒刷新
  206.         setInterval(fetchData, 1000);
  207.         fetchData();
  208.     </script>
  209. </body>
  210. </html>
复制代码


只谈技术、莫论政事!(点击见详情) | 互相尊重、友善交流、切勿过度反应、玻璃心。胡乱输入灌水等操作将会被封禁ID。
回复

使用道具 举报

 楼主| 发表于 2026-6-17 17:19 | 显示全部楼层
我没有把它封装成安装软件包,原因就是我没有数字签名,获得OPENWRT数字签名实在太麻烦了,还不如直接用文件替换。
只谈技术、莫论政事!(点击见详情) | 互相尊重、友善交流、切勿过度反应、玻璃心。胡乱输入灌水等操作将会被封禁ID。
回复

使用道具 举报

 楼主| 发表于 2026-6-17 17:24 | 显示全部楼层
有办法删帖吗?找了半天找不到地方删帖。这个标题有点儿吹牛逼了,都怪语音输入法,我说我重写了露西的一个大屏界面,并没有说我重写露西,我哪有那大本事重写露西呢?这下吹牛吹大了,这还不让删帖了,这还
只谈技术、莫论政事!(点击见详情) | 互相尊重、友善交流、切勿过度反应、玻璃心。胡乱输入灌水等操作将会被封禁ID。
回复

使用道具 举报

发表于 2026-6-17 18:05 | 显示全部楼层
676220229 发表于 2026-6-17 17:24
有办法删帖吗?找了半天找不到地方删帖。这个标题有点儿吹牛逼了,都怪语音输入法,我说我重写了露西的一个 ...

帖子是可以编辑的啊,你编辑就行了,如果确认删帖的话,回复我的帖子,我看到后会删除
只谈技术、莫论政事!(点击见详情) | 互相尊重、友善交流、切勿过度反应、玻璃心。胡乱输入灌水等操作将会被封禁ID。
回复

使用道具 举报

发表于 2026-6-18 13:52 | 显示全部楼层
挺好的 做一个小显示器在路由上就ok了

点评

0.96 寸 3.3V I2C OLED 屏:8~12 元 40P 彩排杜邦线:3 元 公母排针插座(焊接路由 TTL):2 元 双面泡棉胶:1 元 合计:15 元左右 安装依赖:opkg install python3 python3-pillow i2c-tools 开启内核 I2C/SPI 驱  详情 回复 发表于 2026-6-20 01:15
只谈技术、莫论政事!(点击见详情) | 互相尊重、友善交流、切勿过度反应、玻璃心。胡乱输入灌水等操作将会被封禁ID。
回复

使用道具 举报

 楼主| 发表于 2026-6-20 01:15 | 显示全部楼层
欲与伊泰克 发表于 2026-6-18 13:52
挺好的 做一个小显示器在路由上就ok了

0.96 寸 3.3V I2C OLED 屏:8~12 元
40P 彩排杜邦线:3 元
公母排针插座(焊接路由 TTL):2 元
双面泡棉胶:1 元
合计:15 元左右

安装依赖:opkg install python3 python3-pillow i2c-tools
开启内核 I2C/SPI 驱动,在 LuCI 开启 GPIO 权限
用 Python 脚本读取 CPU 温度、内存、WAN 流量、在线时长、负载,推送至屏幕显示(常用开源项目:oled-exp、luci-app-oled、lcd4linux)
豆包说的
只谈技术、莫论政事!(点击见详情) | 互相尊重、友善交流、切勿过度反应、玻璃心。胡乱输入灌水等操作将会被封禁ID。
回复

使用道具 举报

 楼主| 发表于 2026-6-20 01:16 | 显示全部楼层
  1. from PIL import Image, ImageDraw, ImageFont
  2. import smbus2
  3. import time
  4. import os

  5. # I2C配置
  6. I2C_BUS = 0
  7. OLED_ADDR = 0x3C
  8. WIDTH = 128
  9. HEIGHT = 64

  10. bus = smbus2.SMBus(I2C_BUS)

  11. # 初始化SSD1306命令
  12. def oled_init():
  13.     init_cmds = [
  14.         0xAE,0xD5,0x80,0xA8,0x3F,0xD3,0x00,0x40,
  15.         0x8D,0x14,0xA1,0xC8,0xD9,0xF1,0xDA,0x12,
  16.         0xDB,0x40,0xA4,0xA6,0xAF
  17.     ]
  18.     for cmd in init_cmds:
  19.         bus.write_byte_data(OLED_ADDR, 0x00, cmd)

  20. def display_image(img):
  21.     buf = img.tobytes()
  22.     for page in range(8):
  23.         bus.write_byte_data(OLED_ADDR, 0x00, 0xB0 + page)
  24.         bus.write_byte_data(OLED_ADDR, 0x00, 0x00)
  25.         bus.write_byte_data(OLED_ADDR, 0x00, 0x10)
  26.         for x in range(WIDTH):
  27.             bus.write_byte_data(OLED_ADDR, 0x40, buf[page*WIDTH + x])

  28. def get_sys_info():
  29.     load = os.popen("uptime | awk '{print $10,$11,$12}'").read().strip()
  30.     mem = os.popen("free -h | grep Mem | awk '{print $3"/"$2}'").read().strip()
  31.     temp = os.popen("cat /sys/class/thermal/thermal_zone0/temp").read()
  32.     temp = f"{int(int(temp)/1000)}℃"
  33.     wan_ip = os.popen("ifconfig wan | grep inet | awk '{print $2}'").read().strip()
  34.     return load, mem, temp, wan_ip

  35. oled_init()
  36. font = ImageFont.load_default()

  37. while True:
  38.     img = Image.new("1", (WIDTH, HEIGHT), 0)
  39.     draw = ImageDraw.Draw(img)
  40.     load, mem, temp, wan_ip = get_sys_info()
  41.     draw.text((0,0), f"CPU负载:{load}", font=font, fill=255)
  42.     draw.text((0,16), f"内存:{mem}", font=font, fill=255)
  43.     draw.text((0,32), f"温度:{temp}", font=font, fill=255)
  44.     draw.text((0,48), f"WAN:{wan_ip}", font=font, fill=255)
  45.     display_image(img)
  46.     time.sleep(2)
复制代码
只谈技术、莫论政事!(点击见详情) | 互相尊重、友善交流、切勿过度反应、玻璃心。胡乱输入灌水等操作将会被封禁ID。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

欢迎大家光临恩山无线论坛上一条 /2 下一条

有疑问请添加管理员QQ86788181|手机版|小黑屋|Archiver|恩山无线论坛(常州市恩山计算机开发有限公司版权所有) ( 苏ICP备05084872号 )

GMT+8, 2026-8-23 20:44

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

| 江苏省互联网有害信息举报中心 举报信箱:js12377 | @jischina.com.cn 举报电话:025-88802724 本站不良内容举报信箱:68610888@qq.com 电话:13506125623

快速回复 返回顶部 返回列表