---
title: "PicoNetANALyzer"
url: "https://maker.wiznet.io/sophia/projects/piconetanalyzer/"
markdown_url: "https://maker.wiznet.io/sophia/projects/piconetanalyzer/md"
type: "UCC: User Created Content"
author: "theprod45"
author_url: "https://github.com/theprod45/PicoNetANALyzer"
editor: "WIZnet"
editor_url: "https://maker.wiznet.io/"
original_author: "theprod45"
original_url: "https://github.com/theprod45/PicoNetANALyzer"
published: "2026-10-23"
language: "en"
hardware: ["WIZnet WizFi360-EVB-Pico"]
likes: 0
views: 4
comments: 0
source: "WIZnet Makers (https://maker.wiznet.io/)"
---

# PicoNetANALyzer

> PicoNetANALyzer is a lightweight, always-on embedded network monitoring and diagnostics platform built around the WIZnet WizFi360-EVB-Pico.

Original author: theprod45 (source: https://github.com/theprod45/PicoNetANALyzer)

## Components

- **WIZnet WizFi360-EVB-Pico** x 1

## Article

How Does PicoNetANALyzer Turn a WizFi360-EVB-Pico into an Always-On Wi-Fi Health Probe?

Source: https://github.com/theprod45/PicoNetANALyzer (MIT License, © 2026 theprod45; repository listed as last updated August 2026 on GitHub)

PicoNetANALyzer is an open-source network-monitoring probe built on the WIZnet WizFi360-EVB-Pico. The RP2040 talks to the WizFi360 module over UART with AT commands, measures Wi-Fi association state, RTT, jitter, packet loss and DNS health every 5 seconds, and streams the results as one-JSON-object-per-line (NDJSON) over USB to a PC. A Python collector writes everything into SQLite and a FastAPI dashboard shows live graphs and an event timeline. The board keeps no history at all; the host does.

[COMPONENTS]

- WIZnet WizFi360-EVB-Pico — Target board: RP2040 + WizFi360 Wi-Fi module. Only hardware in the BOM besides a USB cable
- WizFi360 (on-board) — 2.4 GHz Wi-Fi station, AT-command interface. Driven over uart1, TX GPIO 4, RX GPIO 5, 115200 baud
- RP2040 (on-board) — Runs the measurement loop and event detector. Pico C/C++ SDK; links pico_stdlib + hardware_uart, USB stdio enabled
- Host PC (Linux) — Collector + database + dashboard. Python 3, pyserial ≥ 3.5, FastAPI, Uvicorn, SQLite
- USB connection — Telemetry path. USB CDC, default /dev/ttyACM0

[PROJECT DESCRIPTION]

▶ Overview

The author's premise is that a laptop running Wireshark is the wrong tool for a question like "does the Wi-Fi in the lab drop out at night?" A dedicated probe that costs little, draws little power and never sleeps is better, and several of them can report into one dashboard (pico-01, pico-02… via DEVICE_ID). PicoNetANALyzer is deliberately not a packet-capture tool; the README is explicit that the WizFi360 is used through its AT interface and that the project monitors connectivity, RTT, DNS and state changes rather than raw frames.

The firmware is three C files (main.c, network_events.c, telemetry.c) plus a config.h that holds the SSID, password and thresholds. The host side is two Python programs: collector.py (serial → SQLite) and dashboard.py (FastAPI REST + browser UI).

▶ The measurement cycle

Every MONITOR_INTERVAL_MS (default 5000 ms) the RP2040 runs a fixed sequence of AT commands against the WizFi360 and parses the replies:

- AT+CWMODE_CUR=1, AT+CWJAP_CUR="ssid","pw" — Station mode and association (15 s timeout on join)
- AT+CWJAP_CUR? — SSID, BSSID, channel, RSSI (parsed with one sscanf)
- AT+CIPSTA_CUR? — IP address, gateway, netmask
- AT+CIPDNS_CUR? — DNS server configuration
- AT+PING="target" — Gateway RTT and Internet RTT (INTERNET_TARGET, default 1.1.1.1)
- AT+CIPDOMAIN="domain" — DNS resolution check (DNS_TEST_DOMAIN, default example.com)

The AT helper flushes stale UART bytes, sends the command with \r\n, and returns as soon as OK or ERROR/FAIL appears in the response buffer (1024 bytes) or the per-command timeout expires.

From the probes the firmware derives min/avg/max RTT since boot, jitter (difference between consecutive successful RTTs), a rolling packet-loss window of PACKET_LOSS_WINDOW_SIZE = 12 samples (about one minute at 5 s intervals, with a minimum of 5 samples before a loss alarm), and counters for disconnects and reconnects.

▶ Diagnostic model and state-based events

Instead of logging every bad sample, the firmware classifies where a problem sits using a short decision tree: Wi-Fi associated? → gateway reachable? → Internet IP reachable? → DNS resolving? The result is one of WIFI_DISCONNECTED, LOCAL_NETWORK_ISSUE, INTERNET_OUTAGE, DNS_FAILURE or ONLINE. Because the ping goes to a raw IP and DNS is tested separately, an ISP outage and a broken resolver produce different events.

Sixteen event types are defined (DEVICE_STARTED, WIFI_CONNECTED, WIFI_CONNECT_FAILED, WIFI_DISCONNECTED, WIFI_RECONNECTED, BSSID_CHANGED, CHANNEL_CHANGED, GATEWAY_CHANGED, WEAK_SIGNAL, HIGH_LATENCY, HIGH_JITTER, HIGH_PACKET_LOSS, INTERNET_OUTAGE, INTERNET_RECOVERED, DNS_FAILURE, DNS_RECOVERED). They are state-based: HIGH_LATENCY fires once when internet_rtt_ms crosses HIGH_RTT_THRESHOLD_MS (default 150 ms) and is not repeated while the condition persists. Outages need INTERNET_FAILURE_THRESHOLD = 2 consecutive failed probes, and DNS failures need DNS_FAILURE_THRESHOLD = 2, so a single lost ping never becomes an alarm. Recovery events carry the outage duration.

Default thresholds in config.example.h: weak signal −75 dBm, high RTT 150 ms, high jitter 50 ms, high packet loss 20 %.

▶ Telemetry, storage and dashboard

Each cycle emits a measurement record and, when something changes, an event record. Both are NDJSON with "schema": 1 and a device_id, for example a measurement with rssi_dbm, gateway_rtt_ms, internet_rtt_ms, jitter_ms, packet_loss_pct, and an event with details: {metric, value, threshold}. The collector adds a host UTC timestamp to every record and stores it three ways in data/piconet.db: the raw JSON in records (so newer firmware fields survive an older collector), structured rows in measurements, and events.

dashboard.py exposes GET /api/status, /api/devices, /api/measurements?limit=100, /api/events?severity=warning, /api/event-types, /api/raw, plus CSV exports at /api/export/measurements.csv and /api/export/events.csv. The browser page at 127.0.0.1:8000 shows live RTT, RSSI, jitter and loss graphs, an event timeline with severity/type filters, and a device selector for multi-probe setups.

▶ WizFi360 architecture: why an AT-command Wi-Fi module fits a probe

The WizFi360 is an 802.11 b/g/n 2.4 GHz module that handles Wi-Fi and the TCP/IP side itself and exposes them to the host MCU through an AT command set over UART (WIZnet's EVB-Pico documentation lists GPIO4/GPIO5 as the UART pair, GPIO6/7 for RTS/CTS and GPIO20 for module reset). For this project that split is the point: the RP2040 never runs a Wi-Fi driver or an IP stack, so the firmware is a few hundred lines of command/response parsing and arithmetic, and the whole measurement loop fits comfortably in RAM with only "small amounts of temporary state". Association, DHCP, ICMP ping and DNS lookup are all services the module already provides (CWJAP, CIPSTA, PING, CIPDOMAIN), which is exactly the set of observations a connectivity probe needs. The trade-off the author names is that an AT-driven module cannot do monitor-mode capture, so deep packet analysis stays on a Linux box.

On the WizFi360-EVB-Pico the module is already wired to the RP2040's uart1 on GP4/GP5, so the project has no hardware build step: flash the UF2, plug in USB, run the collector.

[Related Maker Reading]

PicoNetANALyzer (this project)
- MCU: RP2040
- WIZnet part: WizFi360 (Wi-Fi, AT commands)
- Network role: Wi-Fi station under test
- What it measures: RSSI, BSSID/channel, RTT, jitter, loss, DNS
- Where data lives: Host SQLite + FastAPI dashboard
- Notable feature: State-based events, multi-probe dashboard, CSV export

Cranet: ESP32-S3 Network Diagnostics Handheld (https://maker.wiznet.io/josephsr/projects/cranet-esp32-s3-network-diagnostics-handheld-with-w5500-wired-ethernet-wi-fi-and-ble/)
- MCU: ESP32-S3
- WIZnet part: W5500 (wired Ethernet)
- Network role: Wired + Wi-Fi + BLE diagnostics
- What it measures: Link, IP, discovery, services
- Where data lives: On-device display
- Notable feature: Handheld with three radios

esp32-ethernet-tester (https://maker.wiznet.io/Lihan__/projects/esp32-ethernet-tester/)
- MCU: ESP32
- WIZnet part: W5500 (wired Ethernet)
- Network role: Ethernet link/port tester
- What it measures: Ethernet connectivity
- Where data lives: On-device
- Notable feature: Pocket tester

Artistic clock on WizFi360-EVB-Pico (https://maker.wiznet.io/teamprof/projects/artistic-clock-running-on-wizfi360-evb-pico/)
- MCU: RP2040
- WIZnet part: WizFi360
- Network role: Wi-Fi client for time/data
- What it measures: — (application, not a tester)
- Where data lives: On-device
- Notable feature: Example of WizFi360 as an app board

[FAQ]

Q. Does the Pico store any logs?
No. The README states the board keeps only transient state in RAM; measurements and events are persisted on the host in data/piconet.db.

Q. How is an Internet outage distinguished from a DNS problem?
The Internet probe pings a raw IP (INTERNET_TARGET), and DNS (AT+CIPDOMAIN) is only tested once the IP probe succeeds. Two consecutive failures of each are required before INTERNET_OUTAGE or DNS_FAILURE is raised.

Q. Can several probes feed one dashboard?
Yes. Each board carries a DEVICE_ID, the collector stores it with every record, and the dashboard has a device selector. Running multiple collectors on multiple serial ports is the author's intended multi-location setup.

Q. Is this a Wi-Fi security tool?
Only loosely. BSSID_CHANGED and GATEWAY_CHANGED are logged as diagnostic indicators; the README cautions that they usually mean roaming or DHCP changes, not an attack, and limits use to networks you own or are authorised to test.

Q. What does the build need?
Pico SDK, CMake, Ninja/Make and the ARM GCC toolchain. cmake -S . -B build -G Ninja && cmake --build build produces the UF2 in firmware/build/.

[Korean]

PicoNetANALyzer는 WizFi360-EVB-Pico를 어떻게 상시 가동 Wi-Fi 상태 프로브로 만들었나?

출처: https://github.com/theprod45/PicoNetANALyzer (MIT License, © 2026 theprod45; GitHub 목록 기준 2026년 8월 마지막 업데이트)

PicoNetANALyzer는 WIZnet WizFi360-EVB-Pico로 만든 오픈소스 네트워크 모니터링 프로브다. RP2040이 UART로 WizFi360 모듈에 AT 커맨드를 보내 Wi-Fi 연결 상태, RTT, 지터, 패킷 손실, DNS 상태를 5초마다 측정하고, 결과를 한 줄에 JSON 하나(NDJSON) 형식으로 USB를 통해 PC로 보낸다. Python 수집기가 이를 SQLite에 저장하고 FastAPI 대시보드가 실시간 그래프와 이벤트 타임라인을 보여준다. 보드는 이력을 전혀 저장하지 않고, 호스트가 모두 보관한다.

[COMPONENTS]

- WIZnet WizFi360-EVB-Pico — 타깃 보드: RP2040 + WizFi360 Wi-Fi 모듈. USB 케이블 외 유일한 하드웨어
- WizFi360 (온보드) — 2.4 GHz Wi-Fi 스테이션, AT 커맨드 인터페이스. uart1, TX GPIO 4, RX GPIO 5, 115200 baud
- RP2040 (온보드) — 측정 루프와 이벤트 감지 실행. Pico C/C++ SDK; pico_stdlib + hardware_uart 링크, USB stdio 활성화
- 호스트 PC (Linux) — 수집기 + DB + 대시보드. Python 3, pyserial ≥ 3.5, FastAPI, Uvicorn, SQLite
- USB 연결 — 텔레메트리 경로. USB CDC, 기본 /dev/ttyACM0

[PROJECT DESCRIPTION]

▶ 개요

작성자의 출발점은 "실험실 Wi-Fi가 밤에 끊기는가?" 같은 질문에 Wireshark를 띄운 노트북은 맞지 않는 도구라는 것이다. 값싸고 저전력이며 절대 잠들지 않는 전용 프로브가 더 낫고, 여러 대를 두어 하나의 대시보드로 모을 수 있다(DEVICE_ID로 pico-01, pico-02… 구분). PicoNetANALyzer는 의도적으로 패킷 캡처 도구가 아니다. README는 WizFi360을 AT 인터페이스로 쓰며, 원시 프레임이 아니라 연결성·RTT·DNS·상태 변화를 감시한다고 명시한다.

펌웨어는 C 파일 세 개(main.c, network_events.c, telemetry.c)와 SSID·비밀번호·임계값을 담은 config.h로 구성된다. 호스트 쪽은 Python 프로그램 두 개, collector.py(시리얼 → SQLite)와 dashboard.py(FastAPI REST + 브라우저 UI)다.

▶ 측정 주기

MONITOR_INTERVAL_MS(기본 5000 ms)마다 RP2040은 WizFi360에 정해진 순서로 AT 커맨드를 보내고 응답을 파싱한다.

- AT+CWMODE_CUR=1, AT+CWJAP_CUR="ssid","pw" — 스테이션 모드 및 접속 (접속 타임아웃 15초)
- AT+CWJAP_CUR? — SSID, BSSID, 채널, RSSI (sscanf 한 번으로 파싱)
- AT+CIPSTA_CUR? — IP 주소, 게이트웨이, 넷마스크
- AT+CIPDNS_CUR? — DNS 서버 설정
- AT+PING="target" — 게이트웨이 RTT와 인터넷 RTT (INTERNET_TARGET, 기본 1.1.1.1)
- AT+CIPDOMAIN="domain" — DNS 해석 확인 (DNS_TEST_DOMAIN, 기본 example.com)

AT 헬퍼는 남아 있는 UART 바이트를 비우고 \r\n으로 끝나는 명령을 보낸 뒤, 응답 버퍼(1024바이트)에 OK 또는 ERROR/FAIL이 나타나거나 명령별 타임아웃이 지나면 즉시 반환한다.

프로브 결과로 부팅 이후 최소/평균/최대 RTT, 지터(연속된 성공 RTT 간 차이), PACKET_LOSS_WINDOW_SIZE = 12 샘플의 롤링 패킷 손실률(5초 간격에서 약 1분, 손실 경보 전 최소 5개 샘플 필요), 끊김·재접속 카운터를 계산한다.

▶ 진단 모델과 상태 기반 이벤트

나쁜 샘플을 매번 기록하는 대신, 펌웨어는 짧은 결정 트리로 문제가 어디에 있는지 분류한다. Wi-Fi 접속됨? → 게이트웨이 도달? → 인터넷 IP 도달? → DNS 해석? 결과는 WIFI_DISCONNECTED, LOCAL_NETWORK_ISSUE, INTERNET_OUTAGE, DNS_FAILURE, ONLINE 중 하나다. 핑은 IP 주소로 직접 보내고 DNS는 따로 검사하므로, ISP 장애와 리졸버 고장이 서로 다른 이벤트로 나온다.

이벤트 타입은 16종이다(DEVICE_STARTED, WIFI_CONNECTED, WIFI_CONNECT_FAILED, WIFI_DISCONNECTED, WIFI_RECONNECTED, BSSID_CHANGED, CHANNEL_CHANGED, GATEWAY_CHANGED, WEAK_SIGNAL, HIGH_LATENCY, HIGH_JITTER, HIGH_PACKET_LOSS, INTERNET_OUTAGE, INTERNET_RECOVERED, DNS_FAILURE, DNS_RECOVERED). 모두 상태 기반이어서 HIGH_LATENCY는 internet_rtt_ms가 HIGH_RTT_THRESHOLD_MS(기본 150 ms)를 넘는 순간 한 번만 발생하고 조건이 지속되는 동안 반복되지 않는다. 장애 판정에는 INTERNET_FAILURE_THRESHOLD = 2회 연속 실패, DNS 장애에는 DNS_FAILURE_THRESHOLD = 2회가 필요해 핑 한 번 놓친 것이 경보가 되지 않는다. 복구 이벤트에는 장애 지속 시간이 담긴다.

config.example.h의 기본 임계값: 약신호 −75 dBm, 고지연 150 ms, 고지터 50 ms, 고손실 20 %.

▶ 텔레메트리, 저장, 대시보드

매 주기마다 measurement 레코드가, 변화가 있을 때 event 레코드가 출력된다. 둘 다 "schema": 1과 device_id를 가진 NDJSON이며, 측정 레코드에는 rssi_dbm, gateway_rtt_ms, internet_rtt_ms, jitter_ms, packet_loss_pct 등이, 이벤트에는 details: {metric, value, threshold}가 들어간다. 수집기는 모든 레코드에 호스트 UTC 타임스탬프를 붙여 data/piconet.db에 세 가지로 저장한다. 원본 JSON은 records에(새 펌웨어 필드가 옛 수집기에서도 보존되도록), 정형 행은 measurements와 events에.

dashboard.py는 GET /api/status, /api/devices, /api/measurements?limit=100, /api/events?severity=warning, /api/event-types, /api/raw와 CSV 내보내기 /api/export/measurements.csv, /api/export/events.csv를 제공한다. 127.0.0.1:8000의 브라우저 페이지는 RTT·RSSI·지터·손실 실시간 그래프, 심각도/타입 필터가 있는 이벤트 타임라인, 다중 프로브용 장치 선택기를 보여준다.

▶ WizFi360 아키텍처: AT 커맨드 Wi-Fi 모듈이 프로브에 맞는 이유

WizFi360은 802.11 b/g/n 2.4 GHz 모듈로, Wi-Fi와 TCP/IP 처리를 스스로 담당하고 호스트 MCU에는 UART 위의 AT 커맨드 세트로 노출한다(WIZnet EVB-Pico 문서 기준 UART는 GPIO4/GPIO5, RTS/CTS는 GPIO6/7, 모듈 리셋은 GPIO20). 이 프로젝트에서는 바로 그 분리가 핵심이다. RP2040은 Wi-Fi 드라이버도 IP 스택도 실행하지 않으므로 펌웨어는 명령/응답 파싱과 산술 몇백 줄로 끝나고, 측정 루프 전체가 "소량의 임시 상태"만으로 RAM에 여유 있게 들어간다. 접속, DHCP, ICMP 핑, DNS 조회는 모듈이 이미 제공하는 서비스(CWJAP, CIPSTA, PING, CIPDOMAIN)이고, 이는 연결성 프로브에 필요한 관측 항목과 정확히 일치한다. 작성자가 밝힌 트레이드오프는 AT 구동 모듈로는 모니터 모드 캡처가 불가능해 심층 패킷 분석은 Linux 장비 몫으로 남는다는 점이다.

WizFi360-EVB-Pico에서는 모듈이 이미 RP2040의 uart1(GP4/GP5)에 배선돼 있어 하드웨어 작업이 없다. UF2를 굽고, USB를 꽂고, 수집기를 실행하면 된다.

[Related Maker Reading]

PicoNetANALyzer (이 프로젝트)
- MCU: RP2040
- WIZnet 부품: WizFi360 (Wi-Fi, AT 커맨드)
- 네트워크 역할: 감시 대상 Wi-Fi 스테이션
- 측정 항목: RSSI, BSSID/채널, RTT, 지터, 손실, DNS
- 데이터 위치: 호스트 SQLite + FastAPI 대시보드
- 특징: 상태 기반 이벤트, 다중 프로브 대시보드, CSV 내보내기

Cranet: ESP32-S3 네트워크 진단 핸드헬드 (https://maker.wiznet.io/josephsr/projects/cranet-esp32-s3-network-diagnostics-handheld-with-w5500-wired-ethernet-wi-fi-and-ble/)
- MCU: ESP32-S3
- WIZnet 부품: W5500 (유선 이더넷)
- 네트워크 역할: 유선 + Wi-Fi + BLE 진단
- 측정 항목: 링크, IP, 탐색, 서비스
- 데이터 위치: 기기 디스플레이
- 특징: 라디오 3종 핸드헬드

esp32-ethernet-tester (https://maker.wiznet.io/Lihan__/projects/esp32-ethernet-tester/)
- MCU: ESP32
- WIZnet 부품: W5500 (유선 이더넷)
- 네트워크 역할: 이더넷 링크/포트 테스터
- 측정 항목: 이더넷 연결성
- 데이터 위치: 기기
- 특징: 포켓 테스터

WizFi360-EVB-Pico 아트 시계 (https://maker.wiznet.io/teamprof/projects/artistic-clock-running-on-wizfi360-evb-pico/)
- MCU: RP2040
- WIZnet 부품: WizFi360
- 네트워크 역할: 시간/데이터용 Wi-Fi 클라이언트
- 측정 항목: — (테스터가 아닌 응용)
- 데이터 위치: 기기
- 특징: WizFi360 응용 보드 예시

[FAQ]

Q. Pico에 로그가 저장되나요?
아니요. README는 보드가 RAM에 일시적 상태만 유지한다고 밝히며, 측정값과 이벤트는 호스트의 data/piconet.db에 저장됩니다.

Q. 인터넷 장애와 DNS 문제를 어떻게 구분하나요?
인터넷 프로브는 IP 주소(INTERNET_TARGET)로 핑을 보내고, DNS(AT+CIPDOMAIN)는 IP 프로브가 성공한 뒤에만 검사합니다. 각각 2회 연속 실패해야 INTERNET_OUTAGE 또는 DNS_FAILURE가 발생합니다.

Q. 프로브 여러 대를 한 대시보드에 모을 수 있나요?
네. 보드마다 DEVICE_ID가 있고 수집기가 모든 레코드에 이를 저장하며 대시보드에 장치 선택기가 있습니다. 여러 시리얼 포트에 수집기를 여러 개 띄우는 것이 작성자가 의도한 다지점 구성입니다.

Q. Wi-Fi 보안 도구인가요?
제한적입니다. BSSID_CHANGED와 GATEWAY_CHANGED는 진단 지표로 기록되며, README는 이것이 보통 로밍이나 DHCP 변경이지 공격이 아니라고 주의를 주고, 소유하거나 허가받은 네트워크에서만 사용하라고 합니다.

Q. 빌드에 무엇이 필요한가요?
Pico SDK, CMake, Ninja/Make, ARM GCC 툴체인. cmake -S . -B build -G Ninja && cmake --build build로 firmware/build/에 UF2가 생성됩니다.

[Documents]

- Source repository (MIT) — https://github.com/theprod45/PicoNetANALyzer
- Firmware entry point (main.c, AT handling) — https://github.com/theprod45/PicoNetANALyzer/blob/main/firmware/main.c
- Configuration template — https://github.com/theprod45/PicoNetANALyzer/blob/main/firmware/config.example.h
- Host collector / dashboard — https://github.com/theprod45/PicoNetANALyzer/tree/main/host
- WizFi360-EVB-Pico product page — https://wiznet.io/products/evaluation-boards/wizfi360-evb-pico
- WizFi360-EVB-Pico documentation (pinout: GPIO4/5 UART, GPIO6/7 RTS/CTS, GPIO20 reset) — https://docs.wiznet.io/Product/Open-Source-Hardware/wizfi360-evb-pico
- Raspberry Pi Pico C/C++ SDK — https://github.com/raspberrypi/pico-sdk

Original author: theprod45 (GitHub). Content paraphrased from the repository README and source; no values beyond those in the repository are claimed.

---

Source: https://maker.wiznet.io/sophia/projects/piconetanalyzer/
