idf.py flash monitor
```
--------------------------------
### Start Train Automation Ticker
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Starts an interval timer that calls 'renderTrainAutomationStatus' every 250ms to provide real-time updates. Clears any existing ticker first.
```javascript
function startTrainAutomationTicker() {
clearTrainAutomationTicker();
trainAutomation.tickerTimer = window.setInterval(renderTrainAutomationStatus, 250);
renderTrainAutomationStatus();
}
```
--------------------------------
### Set Component Compile Options
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/connect_rainmaker/main/CMakeLists.txt
Applies a specific compile option to the component library. This example disables format string warnings.
```cmake
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
```
--------------------------------
### ESP-CRAB CSI Data Format Example
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-crab/README.md
This is an example of the CSI data printed to the serial port by the ESP-CRAB device. It includes various parameters related to the Wi-Fi packet reception.
```text
CSI_DATA,3537,1a:00:00:00:00:00,-17,11,159,22,5,8,859517,47,0,234,0,"[14,9,13,...,-11]"
```
--------------------------------
### Run CSI Visualization Tool
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/console_test/README.md
Installs Python dependencies and launches the `esp_csi_tool.py` script for visualizing CSI data. Ensure `idf.py monitor` is closed before running this command. Use the UART port for communication.
```bash
cd esp-csi/examples/console_test/tools
# Install python related dependencies
pip install -r requirements.txt
# Graphical display
python esp_csi_tool.py -p /dev/ttyUSB1
```
--------------------------------
### Start Render Loop Function
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Initializes a recurring interval timer to call the renderAll function, ensuring the UI is continuously updated. Prevents multiple timers from being created if already running.
```javascript
function startRenderLoop() {
if (redrawTimer) {
return;
}
redrawTimer = window.setInterval(renderAll, 120);
}
```
--------------------------------
### Get Display Source
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Returns the current state or a paused snapshot of the state, depending on whether the UI is paused.
```javascript
function getDisplaySource() {
return state.uiPaused && state.pausedSnapshot ? state.pausedSnapshot : state;
}
```
--------------------------------
### Start Delayed Training Function
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Initiates training on a selected peer with optional delay and duration. Handles stopping any ongoing training before scheduling the new one. Logs the scheduled training event.
```javascript
async function startDelayedTraining() {
if (!selectedPeer) {
logEvent(t("logTrainNoPeer"));
return;
}
const peerName = selectedPeer;
const delayValue = Number(trainDelayInput.value || 0);
const durationValue = Number(trainDurationInput.value || 0);
const delaySec = Number.isFinite(delayValue) ? Math.max(0, delayValue) : 0;
const durationSec = Number.isFinite(durationValue) ? Math.max(1, durationValue) : 1;
if (trainAutomation.phase === "running" && trainAutomation.peer) {
await sendTrainCommand("TRAIN_STOP", trainAutomation.peer);
}
cancelTrainAutomation(null);
if (delaySec <= 0) {
await beginAutomatedTraining(peerName, durationSec);
return;
}
trainAutomation.phase = "waiting";
trainAutomation.peer = peerName;
trainAutomation.startAtMs = Date.now() + delaySec * 1000;
trainAutomation.startTimer = window.setTimeout(async () => {
await beginAutomatedTraining(peerName, durationSec);
}, delaySec * 1000);
startTrainAutomationTicker();
logEvent(`${t("logTrainScheduled")}: ${peerName}, delay=${delaySec}s, duration=${durationSec}s`);
}
```
--------------------------------
### Example CSI Data Output
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/csi_recv_router/README.md
This snippet shows the typical output format for CSI data captured by the ESP32. It includes MAC addresses, signal strength, and a detailed array of CSI values.
```text
CSI_DATA,12,94:d9:b3:80:8c:81,-32,11,1,7,1,0,1,0,1,0,0,-93,0,13,2,2921403,0,67,0,128,1,"[67,48,4,0,0,0,0,0,0,0,-6,0,-24,2,-23,1,-22,0,-21,-1,-20,-1,-18,-1,-16,0,-15,1,-14,3,-13,5,-13,7,-14,8,-15,9,-16,10,-17,10,-17,9,-18,9,-17,8,-17,7,-16,6,-15,5,-13,5,-12,6,-10,6,-9,7,-8,8,-4,5,-8,11,-8,12,-8,12,-9,13,-10,13,-11,12,-11,12,-11,11,-10,10,-9,9,-8,8,-7,8,-6,8,-4,9,-3,9,-3,10,-3,11,-3,12,-3,12,-4,13,-5,13,-6,13,-6,12,-7,11,-6,10,-6,9,-2,2,0,0,0,0,0,0,0,0]"
CSI_DATA,13,94:d9:b3:80:8c:81,-32,11,1,7,1,0,1,0,1,0,0,-93,0,13,2,2936234,0,67,0,128,1,"[67,48,4,0,0,0,0,0,0,0,-6,-1,-23,-1,-23,-1,-22,-2,-21,-3,-19,-3,-18,-2,-16,-1,-14,0,-14,2,-13,4,-14,5,-14,7,-16,8,-17,8,-18,8,-18,7,-18,6,-18,6,-18,5,-17,5,-15,4,-14,4,-12,4,-11,5,-9,6,-9,7,-5,4,-9,10,-9,11,-10,12,-10,12,-11,12,-12,11,-12,10,-11,9,-11,9,-10,8,-9,7,-8,7,-6,8,-5,8,-5,9,-4,10,-4,11,-4,11,-5,12,-5,12,-6,13,-7,12,-8,12,-8,10,-8,9,-7,8,-2,2,0,0,0,0,0,0,0,0]"
C
```
--------------------------------
### Chart Enablement and Interaction Setup
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Configures event listeners for chart toggles to manage which charts are displayed and binds chart interactions for zooming and panning.
```javascript
chartToggleConfigs.forEach((config) => {
const input = document.getElementById(config.inputId);
if (!input) {
return;
}
input.checked = state.chartEnabled[config.key] === true;
input.addEventListener("change", () => {
state.chartEnabled[config.key] = input.checked;
applyChartEnabled(config.key);
if (state.uiPaused) {
renderAll(true);
} else {
scheduleRender();
}
});
});
applyAllChartEnabled();
bindChartInteractions(phaseCanvas, state.chartViews.phase);
bindChartInteractions(iqCanvas, state.chartViews.iq);
bindChartInteractions(amplitudeCanvas, state.chartViews.amplitude);
bindChartInteractions(phaseHistoryCanvas, state.chartViews.phaseHistory);
```
--------------------------------
### Get Selected Peer Samples
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Retrieves the samples associated with the currently selected peer. Returns an empty array if no peer is selected or if the peer has no samples.
```javascript
function getSelectedSamples() { const peer = selectedPeer ? peers.get(selectedPeer) : null; return peer?.samples || []; }
```
--------------------------------
### Get Sample Ratio Text
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Returns the applied sample stride as a formatted string (e.g., '3:1').
```javascript
function getSampleRatioText() {
return String(state.appliedSampleStride) + ":1";
}
```
--------------------------------
### CMakeLists.txt Boilerplate Configuration
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-crab/slave_recv/CMakeLists.txt
Essential CMake commands that must be included in your project's CMakeLists.txt file in the specified order for the build system to operate correctly. This setup is standard for ESP-IDF projects.
```cmake
cmake_minimum_required(VERSION 3.5)
add_compile_options(-fdiagnostics-color=always)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
message("EXTRA_COMPONENT_DIRS: " ${EXTRA_COMPONENT_DIRS})
add_definitions(-D CHIP_ID=0)
string(REGEX REPLACE ".*/\(.*".*:" \1 CURDIR ${CMAKE_CURRENT_SOURCE_DIR})
project(${CURDIR})
git_describe(PROJECT_VERSION ${COMPONENT_DIR})
message("Project commit: " ${PROJECT_VERSION})
```
--------------------------------
### Start Serial Data Reading Loop
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Continuously reads data from the serial port, decodes it, and processes each line. Handles read errors and connection termination.
```javascript
async function startReadLoop() {
if (!state.port?.readable) {
return;
}
const decoder = new TextDecoder();
let buffer = "";
try {
state.reader = state.port.readable.getReader();
while (true) {
const { value, done } = await state.reader.read();
if (done) {
break;
}
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() || "";
for (const rawLine of lines) {
handleSerialLine(rawLine.replace(/\r$/, ""));
}
}
} catch (error) {
if (!state.disconnecting) {
addEvent("eventReadError", { message: error.message });
}
} finally {
if (state.reader) {
state.reader.releaseLock();
state.reader = null;
}
if (state.connected && !state.disconnecting) {
await disconnectSerial(false);
addEvent("eventReadEnded");
}
}
}
```
--------------------------------
### Get History Live Window X
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Calculates the visible X-axis range for history charts based on packet IDs and a default window size. Returns null if no valid packet IDs are found.
```javascript
function getHistoryLiveWindowX(packetIds) {
if (packetIds.length === 0) {
return null;
}
let firstId = Number.POSITIVE_INFINITY;
let lastId = Number.NEGATIVE_INFINITY;
for (let i = 0; i < packetIds.length; i += 1) {
const v = packetIds[i];
if (!Number.isFinite(v)) continue;
if (v < firstId) firstId = v;
if (v > lastId) lastId = v;
}
if (!Number.isFinite(firstId) || !Number.isFinite(lastId)) {
return null;
}
const liveMin = Math.max(firstId, lastId - (DEFAULT_HISTORY_WINDOW_SIZE - 1));
return { min: liveMin, max: lastId };
}
```
--------------------------------
### Get Input Sample Stride
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Retrieves the sample stride value from the input element, ensuring it's a finite number greater than or equal to 1. Defaults to 3 if invalid.
```javascript
function getInputSampleStride() {
const value = Number.parseInt(sampleStrideInput.value, 10);
return Number.isFinite(value) && value >= 1 ? value : 3;
}
```
--------------------------------
### Start Serial Read Loop
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Continuously reads data from the serial port, decodes it, and processes incoming lines. It buffers data, splits it into lines, appends raw lines to the log, and attempts to parse JSON messages.
```javascript
async function startReadLoop() {
if (!port?.readable) {
return;
}
reader = port.readable.getReader();
let buffer = "";
try {
while (true) {
const { value, done } = await reader.read();
if (done) {
break;
}
buffer += new TextDecoder().decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop();
for (const rawLine of lines) {
const line = rawLine.replace(/\r$/, "");
appendRawLine(line);
const trimmedLine = line.trim();
if (!trimmedLine) {
continue;
}
if (!trimmedLine.startsWith(HMS_PREFIX)) {
continue;
}
try {
handleMessage(JSON.parse(trimmedLine.slice(HMS_PREFIX.length)));
} catch (error) {
logEvent(`${t("logJsonParseFailed")}: ${error.message}`);
}
}
}
} catch (error) {
logEvent(`${t("logReadEnded")}: ${error.message}`);
} finally {
if (reader) {
reader.releaseLock();
reader = null;
}
}
}
```
--------------------------------
### Configure Project
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/csi_recv_router/README.md
Open the project configuration menu to set up Wi-Fi or Ethernet connections. Refer to the ESP-IDF protocols README for detailed connection instructions.
```bash
idf.py menuconfig
```
--------------------------------
### Serve Demo Directory Locally
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/README.md
Command to serve the 'tools' directory locally using Python's http.server. This is useful if the browser blocks file:// access for Web Serial.
```bash
cd tools
python3 -m http.server
```
--------------------------------
### Initialize and Update Configuration Form
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Handles the initialization and updating of the configuration form based on device settings. It clears the form, sets placeholders, and populates input fields with current configuration values.
```javascript
const placeholder = (!peer?.cfg) ? t("configWaitingPlaceholder") : "";
for (const input of Object.values(configInputs)) {
input.placeholder = placeholder;
}
```
```javascript
function clearConfigForm() {
for (const input of Object.values(configInputs)) {
input.value = "";
}
setConfigFormEnabled(false);
updateConfigFormPlaceholder();
}
```
```javascript
function hydrateConfigForm() {
const peer = selectedPeer ? peers.get(selectedPeer) : null;
if (!peer?.cfg) {
clearConfigForm();
return;
}
for (const [key, input] of Object.entries(configInputs)) {
const v = peer.cfg[key];
if (v !== undefined && v !== null && v !== "") {
input.value = String(v);
} else if (key === "presence_sensitivity") {
input.value = "0.25";
} else {
input.value = "";
}
}
setConfigFormEnabled(true);
updateConfigFormPlaceholder();
}
```
--------------------------------
### Interpolate RGB Color
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Interpolates an RGB color between a start and end color based on a value within a min/max range.
```javascript
function interpolateColor(start, end, value, min, max) {
if (max <= min) {
return "rgb(" + end.join(",") + ")";
}
const ratio = (value - min) / (max - min);
const rgb = start.map((channel, index) => {
return Math.round(channel + (end[index] - channel) * ratio);
});
return "rgb(" + rgb.join(",") + ")";
}
```
--------------------------------
### Clear Train Automation Timers
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Clears all active timers associated with train automation (start, stop, ticker) to prevent them from firing.
```javascript
function clearTrainAutomationTimers() {
if (trainAutomation.startTimer !== null) {
window.clearTimeout(trainAutomation.startTimer);
trainAutomation.startTimer = null;
}
if (trainAutomation.stopTimer !== null) {
window.clearTimeout(trainAutomation.stopTimer);
trainAutomation.stopTimer = null;
}
if (trainAutomation.tickerTimer !== null) {
window.clearInterval(trainAutomation.tickerTimer);
trainAutomation.tickerTimer = null;
}
}
```
--------------------------------
### Registering Project Components and Sources
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-crab/master_recv/main/CMakeLists.txt
This snippet shows how to define source directories and register them with the ESP-IDF build system. It uses `file(GLOB_RECURSE)` to find all `.c` files in specified directories and then registers these sources and include directories using `idf_component_register`.
```cmake
set(LV_UI_DIR ui)
file(GLOB_RECURSE LV_UI_SOURCES ${LV_UI_DIR}/*.c)
set(APP_DIR app)
file(GLOB_RECURSE APP_SOURCES ${APP_DIR}/*.c)
idf_component_register(SRCS "app_main.c" ${LV_UI_SOURCES} ${APP_SOURCES}
INCLUDE_DIRS "." ${LV_UI_DIR} ${APP_DIR})
```
--------------------------------
### Get Viewport Axis Range
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Calculates the appropriate axis range for a chart viewport, considering user-defined views, base ranges, and constraints.
```javascript
function getViewportAxisRange(viewMin, viewMax, baseMin, baseMax, opts) {
const baseSpan = Math.max(baseMax - baseMin, 1e-9);
const minSpan = Math.max(baseSpan * 0.005, 1e-6);
const maxSpan = baseSpan * 20;
let min = Number.isFinite(viewMin) ? viewMin : baseMin;
let max = Number.isFinite(viewMax) ? viewMax : baseMax;
if (!(max > min)) {
min = baseMin;
max = baseMax;
}
if (opts && opts.freeRange && Number.isFinite(viewMin) && Number.isFinite(viewMax) && viewMax > viewMin) {
return { min, max, baseSpan, minSpan };
}
let span = max - min;
if (span > maxSpan) {
const center = (min + max) / 2;
min = center - maxSpan / 2;
max = center + maxSpan / 2;
span = maxSpan;
}
if (span > baseSpan) {
return { min, max, baseSpan, minSpan };
}
if (span < minSpan) {
const center = (min + max) / 2;
min = center - minSpan / 2;
max = center + minSpan / 2;
span = max - min;
}
if (min < baseMin) {
max += baseMin - min;
min = baseMin;
}
if (max > baseMax) {
min -= max - baseMax;
max = baseMax;
}
if (min < baseMin) {
min = baseMin;
}
if (max > baseMa
}
```
--------------------------------
### Get Canvas Local Point
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Converts client coordinates (relative to the viewport) to coordinates local to the canvas element. Useful for precise positioning within the canvas.
```javascript
function getCanvasLocalPoint(canvas, clientX, clientY) {
const rect = canvas.getBoundingClientRect();
return { x: clientX - rect.left, y: clientY - rect.top };
}
```
--------------------------------
### Initialize Chart Viewports
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Creates and initializes viewport objects for different charts based on canvas elements. Sets up initial state for chart axes and domains.
```javascript
const phaseCanvas = document.getElementById("phaseCanvas");
const iqCanvas = document.getElementById("iqCanvas");
const amplitudeCanvas = document.getElementById("amplitudeCanvas");
const phaseHistoryCanvas = document.getElementById("phaseHistoryCanvas");
function createChartViewport(canvas) {
return {
canvas,
xActive: false,
yActive: false,
xMin: null,
xMax: null,
yMin: null,
yMax: null,
plotRect: null,
baseDomain: null,
currentDomain: null,
freeX: false,
xPartner: null,
};
}
state.chartViews = {
phase: createChartViewport(phaseCanvas),
iq: createChartViewport(iqCanvas),
amplitude: createChartViewport(amplitudeCanvas),
phaseHistory: createChartViewport(phaseHistoryCanvas),
};
state.chartViews.amplitude.freeX = true;
state.chartViews.phaseHistory.freeX = true;
state.chartViews.amplitude.xPartner = state.chartViews.phaseHistory;
state.chartViews.phaseHistory.xPartner = state.chartViews.amplitude;
```
--------------------------------
### Render All UI Components
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Updates the entire user interface, including target information, amplitude logging status, peer list, statistics, and charts.
```javascript
function renderAll() { targetText.textContent = appInfo.target || "-"; amplitudeLogText.textContent = appInfo.amplitude_log_enabled ? "ON" : "OFF"; renderPeerList(); renderStats(); renderCharts(); }
```
--------------------------------
### Peer State and Initialization Labels
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Labels related to the state and initialization of peers or channels.
```javascript
peerStateLabel: "State"
```
```javascript
peerInitLabel: "Init"
```
```javascript
peerJitterLabel: "Jitter"
```
```javascript
peerWanderLabel: "Wander"
```
```javascript
peerTrainThrLabel: "Train wander thr"
```
--------------------------------
### Download Text File
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Initiates a file download for the given text content with the specified filename and MIME type.
```javascript
function downloadText(filename, content, mimeType) {
const blob = new Blob([content], { type: mimeType });
const url = URL.createObjectURL(blob);
const anchor = document.createElement("a");
anchor.href = url;
anchor.download = filename;
anchor.style.display = "none";
document.body.appendChild(anchor);
anchor.click();
setTimeout(() => {
anchor.remove();
URL.revokeObjectURL(url);
}, 0);
}
```
--------------------------------
### Training Status and Action Labels
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Defines the possible statuses and actions during the training process.
```javascript
trainStatusNone: "none"
```
```javascript
trainStatusProgress: "in progress"
```
```javascript
trainStatusComplete: "complete"
```
```javascript
trainActionIdle: "idle"
```
```javascript
trainActionWaitBuffer: "waiting buffer"
```
```javascript
trainActionDiscardOutlier: "discard outlier"
```
```javascript
trainActionCollectSample: "collect sample"
```
```javascript
trainActionAccumulateBackground: "accumulate bg"
```
--------------------------------
### Configuration Panel Labels
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Labels for various configuration options within the settings panel.
```javascript
configPanelTitle: "配置面板"
```
```javascript
cfgMotionSensitivityLabel: "运动检测灵敏度"
```
```javascript
cfgPresenceSensitivityLabel: "存在检测灵敏度"
```
```javascript
applyConfigBtn: "应用当前配置"
```
```javascript
configWaitingPlaceholder: "等待设备同步..."
```
--------------------------------
### Handle Manual Train Stop Function
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Stops an ongoing or scheduled training session. If the training is in a 'waiting' state, it cancels the scheduled start. Otherwise, it sends a TRAIN_STOP command to the peer.
```javascript
async function handleManualTrainStop() {
if (trainAutomation.phase === "waiting") {
cancelTrainAutomation("logTrainDelayCancelled");
return;
}
const peerName = trainAutomation.peer || selectedPeer;
if (!peerName) {
logEvent(t("logTrainNoPeer"));
return;
}
cancelTrainAutomation("logTrainTimerCleared");
await sendTrainCommand("TRAIN_STOP", peerName);
}
```
--------------------------------
### Get Chart Interaction Region
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Identifies which region of the chart the client coordinates correspond to (plot area, x-axis, y-axis, or outside). Essential for handling different types of user interactions.
```javascript
function getChartInteractionRegion(view, clientX, clientY) {
if (!view.plotRect) {
return "outside";
}
const point = getCanvasLocalPoint(view.canvas, clientX, clientY);
const plotLeft = view.plotRect.left;
const plotRight = view.plotRect.left + view.plotRect.width;
const plotTop = view.plotRect.top;
const plotBottom = view.plotRect.top + view.plotRect.height;
if (
point.x >= plotLeft &&
point.x <= plotRight &&
point.y >= plotTop &&
point.y <= plotBottom
) {
return "plot";
}
if (
point.x >= plotLeft &&
point.x <= plotRight &&
point.y > plotBottom &&
point.y <= view.canvas.clientHeight
) {
return "x-axis";
}
if (
point.x >= 0 &&
point.x < plotLeft &&
point.y >= plotTop &&
point.y <= plotBottom
) {
return "y-axis";
}
return "outside";
}
```
--------------------------------
### Flash csi_recv Firmware
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/README.md
Flash the csi_recv firmware onto your development board. Ensure the target is set correctly and use the specified baud rate and serial port.
```shell
cd esp-csi/examples/get-started/csi_recv
idf.py set-target esp32c3
idf.py flash -b 921600 -p /dev/ttyUSB1
```
--------------------------------
### Apply Sample Stride Setting
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Applies the selected sample stride value to the application state and triggers a re-render. It also logs an event indicating the sample stride has been applied.
```javascript
function applySampleStride() {
const stride = getInputSampleStride();
sampleStrideInput.value = String(stride);
state.appliedSampleStride = stride;
scheduleRender();
addEvent("eventSampleStrideApplied", { stride });
}
```
--------------------------------
### Flash csi_send Firmware
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/README.md
Flash the csi_send firmware onto your development board. Ensure the target is set correctly and use the specified baud rate and serial port.
```shell
cd esp-csi/examples/get-started/csi_send
idf.py set-target esp32c3
idf.py flash -b 921600 -p /dev/ttyUSB0 monitor
```
--------------------------------
### Window Resize and Beforeunload Event Handlers
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Handles window resize events to schedule UI rendering and manages the serial port disconnection before the page unloads.
```javascript
window.addEventListener("resize", scheduleRender);
window.addEventListener("beforeunload", () => {
if (state.port) {
disconnectSerial(false);
}
});
```
--------------------------------
### Get Displayed Carrier Indices
Source: https://github.com/espressif/esp-csi/blob/master/examples/get-started/tools/csi_viewer.html
Calculates the indices of carriers to be displayed based on the applied sample stride and the total count of carriers. Ensures at least one index is returned if count > 0.
```javascript
function getDisplayedCarrierIndices(count) {
const stride = state.appliedSampleStride;
const indices = [];
for (let i = 0; i < count; i += stride) {
indices.push(i);
}
if (indices.length === 0 && count > 0) {
indices.push(0);
}
return indices;
}
```
--------------------------------
### ESP Wi-Fi Sensing Web Serial Monitor JavaScript Configuration
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Defines constants and initial states for the ESP Wi-Fi Sensing Web Serial Monitor application. Includes settings for message prefixes, maximum sample/line counts, and timers.
```javascript
const HMS_PREFIX = "HMS:";
const MAX_SAMPLES = 240;
const MAX_RAW_LINES = 400;
const MAX_RAW_CHARS = 120000;
const RAW_LOG_FLUSH_MS = 80;
const peers = new Map();
const peerCards = new Map();
const eventLog = [];
const rawSerialLines = [];
let port = null;
let reader = null;
let writer = null;
let selectedPeer = null;
let appInfo = { target: "-", stream_period_ms: 0, amplitude_log_enabled: false };
let redrawTimer = null;
let rawLogCharCount = 0;
let rawLogFlushTimer = null;
let currentLanguage = "en";
```
--------------------------------
### CMakeLists.txt Configuration for ESP-CRAB Slave Receiver
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-crab/slave_recv/main/CMakeLists.txt
This snippet configures the build process for the ESP-CRAB slave receiver. It sets the application directory, finds all C source files recursively, and registers the component with its source files and include directories.
```cmake
set(APP_DIR app)
file(GLOB_RECURSE APP_SOURCES ${APP_DIR}/*.c)
idf_component_register(SRCS "app_main.c" ${APP_SOURCES}
INCLUDE_DIRS "." ${APP_DIR})
```
--------------------------------
### Compile and Flash CSI Receiver
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/console_test/README.md
Compiles and flashes the `console_test` project to a separate ESP32 DevKitC board. This board will receive and process the Wi-Fi CSI data.
```bash
cd esp-csi/examples/console_test
idf.py set-target esp32s3
idf.py flash -b 921600 -p /dev/ttyUSB1
```
--------------------------------
### Peer Management and Rendering Functions
Source: https://github.com/espressif/esp-csi/blob/master/examples/esp-radar/wifi_sensing_demo/tools/web_serial_monitor.html
Manages peer connections, updates peer information, and renders the peer list UI. Includes functions for state badge styling and selecting active peers.
```javascript
function addPeer(name, mac = "") { if (!peers.has(name)) { peers.set(name, { name, mac, latest: null, cfg: null, samples: [], }); } const peer = peers.get(name); if (mac && !peer.mac) { peer.mac = mac; } if (!selectedPeer) { selectedPeer = name; } return peer; }
function stateBadgeClass(name) { if (name === "ACTIVE") { return "active"; } if (name && name.startsWith("DEBOUNCE")) { return "debounce"; } return ""; }
function selectPeer(name) { if (!name || selectedPeer === name) { return; } selectedPeer = name; hydrateConfigForm(); renderAll(); }
function renderPeerList() { const list = Array.from(peers.values()); const visiblePeers = new Set(); for (const peer of list) { let card = peerCards.get(peer.name); if (!card) { card = document.createElement("div"); card.tabIndex = 0; card.addEventListener("pointerdown", (event) => { event.preventDefault(); selectPeer(peer.name); }); card.addEventListener("keydown", (event) => { if (event.key === "Enter" || event.key === " ") { event.preventDefault(); selectPeer(peer.name); } }); peerCards.set(peer.name, card); } visiblePeers.add(peer.name); card.className = "peer-card" + (peer.name === selectedPeer ? " active" : ""); const latest = peer.latest || {}; const badgeClass = stateBadgeClass(latest.state_name); card.innerHTML =
` ${peer.name} ${latest.state_name || "-"}
`;
peerList.appendChild(card);
}
for (const [name, card] of peerCards.entries()) {
if (!visiblePeers.has(name)) {
card.remove();
peerCards.delete(name);
}
}
}
```