(timeString)
| 3252 | }; |
| 3253 | |
| 3254 | function _wifiHmValue(sp) { |
| 3255 | // Selected metric value for a sample (null if this sample lacks it → grey). |
| 3256 | const m = _WIFI_HM_METRICS[_wifiHm.metric] || _WIFI_HM_METRICS.rssi; |
| 3257 | const v = sp[m.field]; |
| 3258 | return v == null ? null : v; |
| 3259 | } |
| 3260 | |
| 3261 | function _wifiHeatColor(val) { |
| 3262 | const m = _WIFI_HM_METRICS[_wifiHm.metric] || _WIFI_HM_METRICS.rssi; |
| 3263 | const t = Math.max(0, Math.min(1, (val - m.lo) / (m.hi - m.lo))); |
| 3264 | const stops = [[239, 68, 68], [245, 158, 11], [234, 179, 8], [132, 204, 22], [34, 197, 94]]; |
| 3265 | const seg = Math.min(stops.length - 2, Math.floor(t * (stops.length - 1))); |
| 3266 | const f = t * (stops.length - 1) - seg; |
| 3267 | const c = stops[seg].map((v, i) => Math.round(v + (stops[seg + 1][i] - v) * f)); |
| 3268 | return c; |
| 3269 | } |
| 3270 | |
| 3271 | function wifiHeatmapSetMetric(v) { |
| 3272 | _wifiHm.metric = (_WIFI_HM_METRICS[v] || v === 'serving' || v === 'handoff') ? v : 'rssi'; |
| 3273 | wifiHeatmapRender(); |
| 3274 | } |
| 3275 | |
| 3276 | function wifiHeatmapRenderLegend() { |
| 3277 | const el = document.getElementById('wifi-hm-legend'); if (!el) return; |
| 3278 | // Mesh maps have their own legends (node colours / hand-off bands). |
| 3279 | if (_wifiHm.mode !== 'design' && (_wifiHm.metric === 'serving' || _wifiHm.metric === 'handoff')) { |
| 3280 | if (_wifiHm.metric === 'serving') { |
| 3281 | const nodes = _wifiMeshNodeList(); |
| 3282 | const reg = (_wifiHm.data && _wifiHm.data.mesh_nodes) || {}; |
| 3283 | el.innerHTML = '<span>Serving node:</span> ' + (nodes.length ? nodes.map((b, i) => |
| 3284 | `<span class="flex items-center gap-1"><span style="width:10px;height:10px;border-radius:2px;display:inline-block;background:${_wifiMeshColor(b)}"></span>${String.fromCharCode(65 + i)} <span class="text-gray-500 font-mono text-[10px]">${b.slice(9)}</span><span class="text-gray-600">${reg[b] ? ' ' + reg[b].band + 'G ch' + reg[b].channel : ''}</span></span>` |
| 3285 | ).join('') : '<span class="text-gray-500">walk the space to map which node serves where</span>'); |
| 3286 | } else { |
| 3287 | el.innerHTML = '<span>Hand-off overlap:</span>' |
| 3288 | + '<span class="flex items-center gap-1"><span style="width:10px;height:10px;border-radius:2px;display:inline-block;background:#22c55e"></span>good (<6 dB)</span>' |
no outgoing calls
no test coverage detected