()
| 3095 | ctx.restore(); |
| 3096 | ctx.fillStyle = '#38bdf8'; ctx.font = '9px sans-serif'; ctx.textAlign = 'left'; |
| 3097 | ctx.fillText('BT hopping', x0 + 3, baseY - stripH - 3); |
| 3098 | } |
| 3099 | // The x-position of a BLE advertising channel on the 2.4 GHz segment. |
| 3100 | const advX = (freqMhz) => { |
| 3101 | const chFrac = (freqMhz - 2407) / 5; |
| 3102 | return Math.max(r24.x0 + 2, Math.min(r24.x1 - 2, xFor('2.4', chFrac))); |
| 3103 | }; |
| 3104 | // A device is selected → fade the ambient markers so the selection pops. |
| 3105 | const sel = _wifiState.btSelected |
| 3106 | ? (_wifiState.bt.devices || []).find(v => v.mac === _wifiState.btSelected) |
| 3107 | : null; |
| 3108 | const dim = sel ? 0.35 : 1.0; |
| 3109 | // 2) BLE advertising-channel markers at 2402/2426/2480 MHz. |
| 3110 | (i.adv_markers || []).forEach(m => { |
| 3111 | const x = advX(m.freq_mhz); |
| 3112 | const intensity = Math.max(0, Math.min(100, m.intensity || 0)); |
| 3113 | const alpha = (0.25 + (intensity / 100) * 0.5) * dim; |
| 3114 | ctx.strokeStyle = `rgba(129,140,248,${alpha})`; ctx.lineWidth = 2; ctx.setLineDash([3, 3]); |
| 3115 | ctx.beginPath(); ctx.moveTo(x, g.padT + 4); ctx.lineTo(x, baseY); ctx.stroke(); |
| 3116 | ctx.setLineDash([]); |
| 3117 | ctx.fillStyle = `rgba(199,210,254,${dim})`; ctx.font = 'bold 9px sans-serif'; ctx.textAlign = 'center'; |
| 3118 | ctx.fillText('BLE ' + m.adv_channel, x, g.padT + 2); |
| 3119 | }); |
| 3120 | // 3) Selected device: draw its RSSI level as a horizontal line across the |
no test coverage detected