<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Priyanshu Chawda</title>
    <description>The latest articles on DEV Community by Priyanshu Chawda (@priyanshuchawda).</description>
    <link>https://dev.to/priyanshuchawda</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2290145%2F68529cc1-1de0-4137-a02d-e70e21b35de5.jpg</url>
      <title>DEV Community: Priyanshu Chawda</title>
      <link>https://dev.to/priyanshuchawda</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/priyanshuchawda"/>
    <language>en</language>
    <item>
      <title>ESP32 Wi-Fi CSI Observatory: Gemma 4 Turns Noisy Wi-Fi Into Camera-Free Room Intelligence</title>
      <dc:creator>Priyanshu Chawda</dc:creator>
      <pubDate>Sun, 24 May 2026 18:12:49 +0000</pubDate>
      <link>https://dev.to/priyanshuchawda/esp32-wi-fi-csi-observatory-gemma-4-turns-noisy-wi-fi-into-camera-free-room-intelligence-1mo</link>
      <guid>https://dev.to/priyanshuchawda/esp32-wi-fi-csi-observatory-gemma-4-turns-noisy-wi-fi-into-camera-free-room-intelligence-1mo</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-gemma-2026-05-06"&gt;Gemma 4 Challenge: Build with Gemma 4&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;What if a room-awareness system could recognize meaningful activity without capturing a single image or recording a single sound?&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;ESP32 Wi-Fi CSI Observatory&lt;/strong&gt;, a camera-free spatial sensing system that uses Wi-Fi Channel State Information from a low-cost ESP32 DevKit V1 to observe changes inside a room.&lt;/p&gt;

&lt;p&gt;Wi-Fi signals naturally change when a person enters, sits, walks or moves nearby. But those signals are noisy. Raw CSI packets contain spikes, unstable readings, variable packet rates and signal fluctuations that are difficult for a human operator to understand directly.&lt;/p&gt;

&lt;p&gt;That is where &lt;strong&gt;Gemma 4&lt;/strong&gt; becomes central to the project.&lt;/p&gt;

&lt;p&gt;Gemma 4 does not pretend to be a camera. It does not receive face images, video frames or identity information. Instead, it receives compact signal statistics produced from the ESP32 stream, selects an appropriate mathematical filtering strategy, interprets the cleaned evidence safely, explains what the system can and cannot claim, and prepares an actionable Telegram message for the operator.&lt;/p&gt;

&lt;p&gt;The complete flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Real room movement
      ↓
ESP32 Wi-Fi CSI packets
      ↓
Local Python feature extraction
      ↓
Gemma 4 filter and parameter decision
      ↓
Deterministic mathematical signal filtering
      ↓
Occupancy / activity evidence
      ↓
Gemma 4 safe explanation
      ↓
React Observatory + Telegram action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is a live system where invisible RF changes become readable, explainable and actionable — without a camera.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Live ESP32 Observatory
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6qyec4t36x7z1d9a5gjd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6qyec4t36x7z1d9a5gjd.png" alt="ESP live Gemma detection" width="800" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbyh76unwifg7w64mmecu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbyh76unwifg7w64mmecu.png" alt="Live terminal CSI receiver showing BPM, RSSI, subcarriers, and waveform" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The terminal receiver proves that the sensing input is real. During the final demonstration, an ESP32 DevKit V1 connected on &lt;code&gt;COM5&lt;/code&gt; streamed live CSI packets into the processing pipeline. The system displayed packet activity, RSSI, subcarrier behavior, motion energy, exploratory rhythm estimates and activity candidates while the Observatory visualized the same evidence in real time.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: Wi-Fi Signals Are Useful, but Noisy
&lt;/h2&gt;

&lt;p&gt;An ESP32 can observe changes in Wi-Fi signal behavior, but the raw stream is not immediately useful.&lt;/p&gt;

&lt;p&gt;A real CSI window may contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sudden spikes and outliers&lt;/li&gt;
&lt;li&gt;unstable RSSI changes&lt;/li&gt;
&lt;li&gt;short-term jitter&lt;/li&gt;
&lt;li&gt;missing or weak packets&lt;/li&gt;
&lt;li&gt;movement patterns mixed with background noise&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A fixed filter is not always ideal. A window with sharp outliers may need different treatment from a window with smooth but continuously noisy variation.&lt;/p&gt;

&lt;p&gt;Instead of applying one hard-coded smoothing strategy to every case, I used &lt;strong&gt;Gemma 4 as a signal-filtering advisor&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The local pipeline first computes compact numerical features such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sample_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"outlier_ratio"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"signal_std"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.41&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"signal_variance"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.81&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"rssi_std"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.27&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"missing_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gemma 4 then chooses the most suitable filtering approach and parameters from an allowed set:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;moving_average&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;median&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hampel&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;lowpass&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;none&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A structured Gemma decision looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"filter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hampel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"window_size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"outlier_threshold"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lowpass_alpha"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.87&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"reason"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The signal window contains spike-like outliers, so local median replacement is appropriate before interpretation."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an important architectural choice:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Gemma 4 does not fabricate sensor values and does not directly modify raw signal samples. It reasons over numerical evidence and selects the mathematical processing strategy. Deterministic Python code then applies that filter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That separation keeps the pipeline inspectable and reliable.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Gemma 4 Improves the Signal Pipeline
&lt;/h2&gt;

&lt;p&gt;The project combines model reasoning with real numerical tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Mathematical filtering remains deterministic
&lt;/h3&gt;

&lt;p&gt;The local Python engine implements the actual signal-processing methods:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Moving average&lt;/strong&gt; for general smoothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Median filtering&lt;/strong&gt; for short spike noise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hampel filtering&lt;/strong&gt; for statistical outlier replacement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low-pass filtering&lt;/strong&gt; for reducing rapid noise while preserving slower movement trends.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gemma 4 selects which method is appropriate for the current signal window and recommends parameters such as filter window size, outlier threshold or low-pass alpha.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;High outlier ratio
      → Gemma chooses median or Hampel filtering

High continuous signal variation
      → Gemma chooses moving average or low-pass filtering

Clean, stable signal
      → Gemma chooses no unnecessary filtering
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes Gemma useful before the final explanation step. It helps determine how the system should clean and prepare uncertain Wi-Fi evidence before displaying an interpretation.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Gemma converts numerical evidence into meaning
&lt;/h3&gt;

&lt;p&gt;Even after filtering, numbers such as variance, RSSI deviation, activity distance and motion energy are not naturally understandable to most people.&lt;/p&gt;

&lt;p&gt;Without Gemma, the operator might only see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;signal_variance=5.81
signal_std=2.41
rssi_std=1.27
activity_candidate=sitting
quality=GOOD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Gemma 4, the same evidence becomes a safe briefing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The RF evidence is consistent with a stationary occupied room.
Signal quality is usable and motion energy is low, which supports
a sitting activity candidate. This is not visual confirmation and
cannot identify any individual.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the real value of Gemma in this project: it transforms technical RF measurements into understandable human decisions while preserving uncertainty.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Gemma 4 Actually Receives
&lt;/h2&gt;

&lt;p&gt;The explanation model never receives camera frames or personal identity data.&lt;/p&gt;

&lt;p&gt;For the Observatory, Gemma receives a compact structured event containing only the evidence required for interpretation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"source"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"live_esp32"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"signal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"quality"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GOOD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"packet_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1007&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"reasons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"stable packet stream"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"usable signal variance"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"motion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"low_motion"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"display_level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"low"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"persons"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"range"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"candidate_present"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"visual"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"trust"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"trusted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pose_state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sitting_candidate"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"limitations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"single ESP advisory mode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"no identity inference"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"not a medical device"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gemma returns structured JSON for the UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"trusted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"room_interpretation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"The CSI summary supports a stationary occupied-room candidate."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"why"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"signal quality is usable"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"motion level is low"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"activity evidence matches the sitting calibration pattern"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"next_action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Continue monitoring or collect additional labeled sitting windows."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"judge_caption"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Trusted Wi-Fi CSI activity state rendered without camera input."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"telegram_message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Trusted CSI: stationary occupied-room candidate detected. No identity inference."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"confidence"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.86&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives the dashboard a consistent contract: status, explanation, reasons, next action, judge-facing caption, Telegram-safe text and confidence.&lt;/p&gt;




&lt;h2&gt;
  
  
  Gemma 4 Is Also a Safety Layer
&lt;/h2&gt;

&lt;p&gt;Room sensing is powerful, but it is easy to overclaim.&lt;/p&gt;

&lt;p&gt;A noisy signal should not become a confident statement such as “a person is definitely sitting” or “heart rate is accurate.” The system is intentionally built to prevent this.&lt;/p&gt;

&lt;p&gt;The Gemma instruction layer explicitly prevents claims about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;camera-like vision&lt;/li&gt;
&lt;li&gt;personal identity&lt;/li&gt;
&lt;li&gt;medical diagnosis&lt;/li&gt;
&lt;li&gt;true body-pose reconstruction&lt;/li&gt;
&lt;li&gt;certainty when signal quality is weak&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The application also keeps a deterministic trust gate after the model response.&lt;/p&gt;

&lt;p&gt;If the Wi-Fi signal is weak, unstable or blocked, the system does not allow an overconfident explanation to pass through. The final result is downgraded to a warning such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The ESP32 stream is visible, but the signal is not trusted enough
for a room-state claim. Improve packet rate and RSSI stability before
trusting the activity visualization.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means Gemma is not being used merely to produce impressive language. It is being used inside a constrained evidence workflow where unsafe claims are blocked.&lt;/p&gt;




&lt;h2&gt;
  
  
  Calibration Coach: Gemma Helps Improve the Experiment
&lt;/h2&gt;

&lt;p&gt;A Wi-Fi CSI system depends heavily on calibration. The same physical activity can look different depending on router placement, room layout and ESP32 position.&lt;/p&gt;

&lt;p&gt;I collect labeled windows such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;empty&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sitting&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;walking&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The local pipeline stores calibration evidence and evaluates whether enough samples exist for useful classification.&lt;/p&gt;

&lt;p&gt;Gemma 4 then works as a &lt;strong&gt;calibration coach&lt;/strong&gt;. It summarizes the current readiness, explains which labels are underrepresented and recommends the next capture needed to improve the system.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Sitting and empty-room samples are available, but walking evidence is
underrepresented. Capture another walking session with the ESP32 and
router positions unchanged before relying on live activity comparisons.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the experiment easier to improve without hiding the limitations of a single-device prototype.&lt;/p&gt;




&lt;h2&gt;
  
  
  Smart Telegram Alerts From Real Evidence
&lt;/h2&gt;

&lt;p&gt;The system also connects the live interpretation to a useful action: Telegram alerts.&lt;/p&gt;

&lt;p&gt;When presence-like evidence is detected, the application can prepare a short message containing useful information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;detected condition&lt;/li&gt;
&lt;li&gt;supporting signal statistics&lt;/li&gt;
&lt;li&gt;selected filter&lt;/li&gt;
&lt;li&gt;Gemma confidence&lt;/li&gt;
&lt;li&gt;safety-aware interpretation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Trusted CSI: stationary occupied-room candidate detected.
Signal quality is usable and motion is low.
Filter selected: Hampel.
This is RF-based evidence only and does not identify a person.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Telegram flow is intentionally safe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Alerts are based on processed evidence, not raw camera or microphone data.&lt;/li&gt;
&lt;li&gt;A cooldown prevents repeated alert spam.&lt;/li&gt;
&lt;li&gt;In the Observatory UI, the prepared message is visible before sending.&lt;/li&gt;
&lt;li&gt;Delivery requires an explicit user action.&lt;/li&gt;
&lt;li&gt;The interface returns a masked acknowledgment rather than exposing Telegram credentials.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So Gemma does not only explain the result on screen. It helps turn noisy sensor evidence into a concise, safe and actionable notification.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Chose Gemma 4 31B Dense
&lt;/h2&gt;

&lt;p&gt;I used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Primary model: gemma-4-31b-it
Fallback model: gemma-4-26b-a4b-it
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I chose &lt;strong&gt;Gemma 4 31B Dense&lt;/strong&gt; because this project needs careful reasoning over uncertain evidence, not decorative text generation.&lt;/p&gt;

&lt;p&gt;The model must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;select an appropriate filter strategy from numerical signal statistics&lt;/li&gt;
&lt;li&gt;return strict structured JSON for the application&lt;/li&gt;
&lt;li&gt;explain why the evidence supports a candidate state&lt;/li&gt;
&lt;li&gt;avoid overclaiming when the signal is weak&lt;/li&gt;
&lt;li&gt;produce short operator-facing and Telegram-safe messages&lt;/li&gt;
&lt;li&gt;assist calibration decisions using compact experiment summaries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the final operator briefing, reasoning quality matters more than generating many responses quickly. The 31B Dense model is therefore used as the primary advisor.&lt;/p&gt;

&lt;p&gt;I configured &lt;strong&gt;Gemma 4 26B MoE&lt;/strong&gt; as a fallback model so the system can still return a hosted Gemma result when the primary route is unavailable or unsuitable for the current request.&lt;/p&gt;

&lt;p&gt;Both model paths are wrapped with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;structured JSON responses&lt;/li&gt;
&lt;li&gt;deterministic temperature settings&lt;/li&gt;
&lt;li&gt;bounded input summaries&lt;/li&gt;
&lt;li&gt;local fallback rules&lt;/li&gt;
&lt;li&gt;post-model safety gates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lets Gemma contribute meaningfully while the system remains stable and inspectable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────┐
│ ESP32 DevKit V1             │
│ Live Wi-Fi CSI packets      │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│ Python Signal Pipeline      │
│ Parse packets + features    │
│ variance / RSSI / outliers  │
└──────────────┬──────────────┘
               │ compact numerical evidence
               ▼
┌─────────────────────────────┐
│ Gemma 4 Filter Advisor      │
│ Select filter + parameters  │
└──────────────┬──────────────┘
               │ structured decision
               ▼
┌─────────────────────────────┐
│ Deterministic DSP Tools     │
│ Median / Hampel / Low-pass  │
│ Moving average              │
└──────────────┬──────────────┘
               │ cleaned evidence
               ▼
┌─────────────────────────────┐
│ Gemma 4 Explanation Layer   │
│ Trust-aware briefing        │
│ Calibration guidance        │
│ Telegram-safe message       │
└──────────────┬──────────────┘
               │
               ▼
┌─────────────────────────────┐
│ React + Three.js Observatory│
│ Timeline / Avatar / Alerts  │
└─────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;Repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/priyanshuchawda/esp32-ai-builder" rel="noopener noreferrer"&gt;https://github.com/priyanshuchawda/esp32-ai-builder&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Main parts of the project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;src/&lt;/code&gt;, &lt;code&gt;include/&lt;/code&gt;, &lt;code&gt;platformio.ini&lt;/code&gt;: ESP32 firmware workspace for CSI streaming.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;esp32-csi-gemma-filter/python-engine/gemma_advisor.py&lt;/code&gt;: Gemma 4 advisor selecting mathematical filtering strategies from summary features.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;esp32-csi-gemma-filter/python-engine/filters.py&lt;/code&gt;: deterministic moving average, median, Hampel and low-pass filtering implementations.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;esp32-csi-gemma-filter/python-engine/app.py&lt;/code&gt;: live serial processing pipeline connecting ESP32 evidence, Gemma decisions, filtering and alerts.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backend/ai_advice.py&lt;/code&gt;: Gemma-powered Observatory explanation layer with structured output and trust gating.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backend/telegram_delivery.py&lt;/code&gt;: explicit Telegram delivery with masked acknowledgment.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;frontend/&lt;/code&gt;: React/Vite/Three.js Observatory UI showing live evidence, Gemma explanation, calibration state and alert actions.&lt;/li&gt;
&lt;/ul&gt;







&lt;h2&gt;
  
  
  Validation
&lt;/h2&gt;

&lt;p&gt;I tested the system end to end with an ESP32 DevKit V1 connected on &lt;code&gt;COM5&lt;/code&gt;.&lt;br&gt;
omplete path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Real ESP32 packets
→ numerical feature extraction
→ Gemma 4 filter decision
→ mathematical filtering
→ activity candidate
→ trust-aware Gemma explanation
→ Observatory visualization
→ Telegram delivery action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Many room-awareness systems rely on cameras, microphones or specialized radar equipment.&lt;/p&gt;

&lt;p&gt;This project explores a different direction:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no camera frames&lt;/li&gt;
&lt;li&gt;no face images&lt;/li&gt;
&lt;li&gt;no microphone recording&lt;/li&gt;
&lt;li&gt;one low-cost ESP32&lt;/li&gt;
&lt;li&gt;local numerical signal processing&lt;/li&gt;
&lt;li&gt;Gemma 4 reasoning over compact evidence&lt;/li&gt;
&lt;li&gt;explicit safety limits&lt;/li&gt;
&lt;li&gt;actionable operator notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to pretend Wi-Fi signals provide perfect vision.&lt;/p&gt;

&lt;p&gt;The goal is to show that a small, inexpensive sensor plus a carefully constrained open model can turn uncertain RF evidence into something understandable and useful, while remaining respectful of privacy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The most important part of this project is not the dashboard animation or the ESP32 alone.&lt;/p&gt;

&lt;p&gt;It is the complete reasoning loop:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The ESP32 observes invisible Wi-Fi changes.&lt;br&gt;&lt;br&gt;
Mathematical tools extract and clean evidence.&lt;br&gt;&lt;br&gt;
Gemma 4 decides how to interpret that evidence safely.&lt;br&gt;&lt;br&gt;
The Observatory makes it understandable.&lt;br&gt;&lt;br&gt;
Telegram makes it actionable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Gemma 4 transformed this from a raw RF experiment into an evidence-grounded, privacy-aware room intelligence system.&lt;/p&gt;

&lt;p&gt;One ESP32 cannot see like a camera.&lt;/p&gt;

&lt;p&gt;But with careful signal processing and Gemma 4 reasoning, it can explain what the room signal is trying to say.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>gemmachallenge</category>
      <category>gemma</category>
    </item>
  </channel>
</rss>
