Files
esp32-cluster/coordinator/__pycache__/dashboard.cpython-314.pyc
T

197 lines
20 KiB
Plaintext
Raw Normal View History

2026-04-03 14:38:38 +03:00
+
dÏi`7ãó¬aRCt60tRt^RIt^RIt^RIt^RIt^RIt^RIHtH t ^RI
H t H t H
t
]PP]PP!]4R4t]PP]PP!]4RR4t]PP]PP!]4RR4t]PP]PP!]4RR 4t]PP]PP!]4R
4t^t^dtR R lt]!]4t]^kR
RltRRltRDRRllt]3RRlltRRlt]R3RRllt RRlt!RRlt"RRlt#RR lt$R!t%]!R"R#7t&]%!4]&POR$] R%7R&4t(]&POR'4R(4t)]&POR)4R*4t*]&POR+4R,4t+]&POR-4]3R.R/ll4t,]&POR04R14t-]&POR24R34t.]&POR44R54t/]&POR64R74t0]&POR84R9R:l4t1]&POR;4R<4t2]3R=8Xd^RI4t4]4Pj!R>R?R@RARB7R#R#)Ez]
WiFi Recon Dashboard
Reads from events.db (written by udp_ingest.py), serves a live web UI.
N)ÚFastAPIÚRequest)Ú HTMLResponseÚStreamingResponseÚ FileResponsez events.dbÚ templateszdashboard.htmlÚstaticz
dashboard.cssz dashboard.jszoui.txtcóRV^8„dQhR\R\\\3,/#)éÚpathÚreturn©ÚstrÚdict)Úformatscoordinator/dashboard.pyÚ __annotate__rs"÷
ñ
”Cð
œD¤¤c 
ócóÌ/p\PPV4'gV#\VRRR7;_uu_4pVFpRV9dK VP R4pV^,P 4P
RR4P4pV^,P 4pV'gKsV'gK}WaV& RRR4V# +'giT#;i)zutf-8Úignore)ÚencodingÚerrorsz(hex)Ú:N)Úosr ÚexistsÚopenÚsplitÚstripÚreplaceÚupper)r ÚdbÚlineÚpartsÚprefixÚvendors& rÚ _load_ouir'Ø€BÜ
7‰7>‰>˜$× Ò Øˆ Ü
ˆd˜W¨X× 6Õ 6¸ˆ˜Ø—JJ˜'ˆ˜1•X—^%×-¨c°3Ó?ˆFؘ1•X—^%ˆ‰vŸ&™&Ø#6“
ñ÷
 €I÷
7Ö 6ð €IúsÁA1CÂ6CÃCÃ C# cóRV^8„dQhR\R\\\3,/#)r
Úmacr )rÚtupleÚbool)rs"rrr+s#÷3”Cð3œE¤#¤t 3rcóZV'd\V4^8dR#\VPRR4PRR4R,^4p\V^,4pT'dR #TP 4R,p\ PTR4R3# \dRu#i;i)
Returns (vendor_name, is_randomized).
Randomized MACs have the locally-administered bit set (bit 1 of first byte).
OUI lookup is meaningless for randomized MACs.
ÚUnknownFrÚr:Nr
N:NéN)r-F)zRandomized MACT)ÚlenÚintrr+Ú
ValueErrorr Ú_OUI_DBÚget)r)Ú
first_byteÚ
randomizedr%s& rÚ
oui_lookupr7+s÷ ”#c“(˜Q”,ؘŸ S¨"Ó-×5°c¸>¸BÀBÓGˆ
ܘ* ,ˆ
֯
Y‰Y‹[˜_€FÜ K‰K˜  Ó *¨EÐ 2øô ô"úsœABÂ
B*Â)B*có8V^8„dQhR\P/#©r
r )Úsqlite3Ú
Connection)rs"rrr?s÷ñ”'×rcód\P!\4p\PVnV#©N)r:ÚconnectÚDB_PATHÚRowÚ row_factory©Úconns rÚget_connrD?s!Ü ?Š?œ7Ó #€DÜ—{‘{€DÔØ €KrcóRV^8„dQhR\R\R\\,/#)r
ÚsqlÚparamsr )rr*Úlistr)rs"rrrEs%÷#Œsð#œEð#¬4´­#rcóÜ\4;_uu_4pVPW4P4pRRR4XUu.uFp\V4NK up# +'giL+;iuupir=)rDÚexecuteÚfetchallr)rFrGrCÚrowsÚrs&& rÚqueryrNEsJÜ Œ|‰|˜CÓ÷
á "™T˜ŒDŽG™TÑ 
üâ "s“ A¿A)Á A& cóJV^8„dQhR\R,R\R\/#)r
Ú last_seenNÚ thresholdr )rr1)rs"rrrKs%÷ñœC $´3ðÌñrcóôV'gR#\PPV4p\PP4V,
P4pW18:dR#R# \dR#i;i)ÚofflineÚonline)ÚdatetimeÚ
fromisoformatÚutcnowÚ
total_secondsr2)rPrQÚdtÚdeltas&& rÚ _node_statusr[Ksgß ÙðÜ
×
Ñ
×
,¨YÓ
7ˆÜ×"×+¨bÕ0ר Ô-ˆ<°9Ð<øÜ ôÚðúsŒAA(Á&A(Á( A7Á6A7có:V^8„dQhR\\,/#r9©rHr)rs"rrrWs÷ñ”Tœ$•Zñrcó\R4p\R4pVUu/uF q"R,VbK ppVpVPVR,/4pVPR4VR&VPR4VR&VPR4VR&VPR4VR&VR,;'g
VR,VR&VR,'d\VR,^R 7VR
&\VR,^<R 7VR
& V#uupi) a
SELECT
node_id,
MAX(received_at) AS last_beacon,
COUNT(*) AS total_events,
MIN(received_at) AS first_seen
FROM beacon_events
GROUP BY node_id
ORDER BY last_beacon DESC
SELECT node_id, received_at AS last_heartbeat,
uptime_ms, free_heap, wifi_rssi
FROM heartbeat_events
WHERE id IN (SELECT MAX(id) FROM heartbeat_events GROUP BY node_id)
Únode_idÚlast_heartbeatÚ uptime_msÚ free_heapÚ wifi_rssiÚ last_beaconrP©rQÚstatus)rNr4r[)rLÚhb_rowsrMÚhb_mapÚhbs rÚ build_nodesrjWsÜ ð ó €Dôðó €Gñ (/Ó
/¡w ! l˜AŠo¡w€FÐ
ˆØ
Z‰Z˜˜)  
Ø Ÿf™fÐ%5ÓÐ
ÑØ Ÿf™f [Óˆ+‰Ø Ÿf™f [Óˆ+‰Ø Ÿf™f [Óˆ+‰ØÐ 0ÕE°Q°}Õ5Eˆˆ+‰à Ð
× Ô Ü& qÐ)9Õ':ÀbÔIˆAˆh& Õ'7À2ÔFˆAˆhð €Kùò0sC?có`V^8„dQhR\R\R,R\\,/#)r
Úlimitr_Nr )r1rrHr)rs"rrrys)÷
ñ
œð
´#¸µ*ð
ÌÌTÍ
ñ
rcóFV'd\RW34#\RV34#)zt
SELECT * FROM beacon_events
WHERE node_id = ?
ORDER BY id DESC LIMIT ?
zJ
SELECT * FROM beacon_events
ORDER BY id DESC LIMIT ?
©rN©rlr_s&&rÚ build_eventsrpys:ßÜð ðÐ
ó ð ô
ðð ˆó ðrcó:V^8„dQhR\\,/#r9r])rs"rrrs÷ñœœT
ñrcó\R4pV#)
SELECT
ssid,
bssid,
MAX(rssi) AS best_rssi,
ROUND(AVG(rssi), 1) AS avg_rssi,
channel,
encryption,
COUNT(*) AS times_seen,
COUNT(DISTINCT node_id) AS node_count,
MAX(received_at) AS last_seen
FROM beacon_events
WHERE bssid IS NOT NULL
GROUP BY bssid
ORDER BY times_seen DESC
rn)rLs rÚbuild_networksrssÜ ðó €Dð €Krcó:V^8„dQhR\\,/#r9r])rs"rrršs÷ñ”tœD•zñrcóÎ\R4pVFNp\RVR,34pVUu.uF q3R,NK
upVR&\VR,4wrEWAR&WQR&KP V#uupi)zK
Per unique src_mac: aggregated stats and the SSIDs they were probing for.
a:
SELECT
src_mac,
COUNT(*) AS times_seen,
COUNT(DISTINCT node_id) AS node_count,
MAX(rssi) AS best_rssi,
ROUND(AVG(rssi), 1) AS avg_rssi,
COUNT(DISTINCT NULLIF(ssid,'')) AS unique_ssids,
MIN(received_at) AS first_seen,
MAX(received_at) AS last_seen
FROM probe_events
WHERE src_mac IS NOT NULL
GROUP BY src_mac
ORDER BY times_seen DESC
z˜
SELECT DISTINCT ssid FROM probe_events
WHERE src_mac = ? AND ssid IS NOT NULL AND ssid != ''
ORDER BY ssid
Úsrc_macÚssidÚ probed_ssidsr&r6)rNr7)rLrMÚ ssid_rowsÚsr&r6s rÚ
build_clientsr{šô ðó €Dó ˆÜð ð lˆ_ó ˆ ñ
1:Ó:± ¨1˜vŸY˜Y± Ñ:ˆˆ.Ñܨ)­ ÓˆØ ˆ(‰ Ø$ˆ,‹ñð €Kùò ;s©A"có$V^8„dQhR\/#r9)r)rs"rrr»s÷226œ$ñ26rc óÊ\R4pVUu.uF qR,NK
pp\R4p/pVFipVR,pWT9d$RVRVR,RVR,RVR,R//WE&R VR ,R
VR
,R VR ,/WE,R,VR,&Kk \VP4R R
R7pVFp\VR,4VR&K RVRV/#uupi)
For every BSSID, return per-node RSSI stats side by side.
Result: { node_ids: [...], networks: [{bssid, ssid, channel, encryption,
node_count, nodes: {node_id: {best_rssi, avg_rssi, times_seen}}}] }
z;SELECT DISTINCT node_id FROM beacon_events ORDER BY node_idr_
SELECT
bssid,
MAX(ssid) AS ssid,
MAX(channel) AS channel,
MAX(encryption) AS encryption,
node_id,
MAX(rssi) AS best_rssi,
ROUND(AVG(rssi), 1) AS avg_rssi,
COUNT(*) AS times_seen
FROM beacon_events
WHERE bssid IS NOT NULL
GROUP BY bssid, node_id
ORDER BY bssid, node_id
ÚbssidrwÚchannelÚ
encryptionÚnodesÚ best_rssiÚavg_rssiÚ
times_seencó&\VR,4#)r)r0)Úxs&rÚ<lambda>Ú"build_cross_node.<locals>.<lambda>çs ”c˜!˜G*”orT)ÚkeyÚreverseÚ
node_countÚnode_idsÚnetworks)rNÚsortedÚvaluesr0)Ú node_rowsrMrLrr~ÚresultÚnets rÚbuild_cross_noder“»s
ô ÐT€IÙ'0Ó1¡y !9—¡y€HÐ ðó €Dð €HÛ
ˆØ'•
ˆØ Ô à˜eؘa ˜a  ˜a  ˜bð ˆH‰Oð
˜!˜K ˜!˜J ˜!˜L2
ˆ˜Õ   9¥Óô ØÓÙ ô€Fó
ˆÜ  G¥ ÓˆLÓñð
˜ *¨fÐ 5ùòW2sC có>V^8„dQhR\R\R,/#)r
r_r Nr
)rs"rrrðs÷$ñ$œsð$¤t¨d¥{ñ$rcó\RV34pV'gR#V^,p\RV34pV'd
V^,M/pVPR4VR&VPR4VR&VPR4VR&VPR4VR&VR,'d\VR,^R7VR&M\VR ,^<R7VR&VR
,'d\VR
,^4MRVR
&\ \
VR 7VR &V#)

SELECT
node_id,
MIN(received_at) AS first_seen,
MAX(received_at) AS last_seen,
COUNT(*) AS total_events,
COUNT(DISTINCT ssid) AS unique_ssids,
COUNT(DISTINCT bssid) AS unique_bssids,
AVG(rssi) AS avg_rssi,
MIN(rssi) AS min_rssi,
MAX(rssi) AS max_rssi
FROM beacon_events
WHERE node_id = ?
GROUP BY node_id
Nz¬
SELECT received_at AS last_heartbeat, uptime_ms, free_heap, wifi_rssi
FROM heartbeat_events
WHERE node_id = ?
ORDER BY id DESC LIMIT 1
r`rarbrcrerfrProÚevents)rNr4r[ÚroundrpÚ EVENT_CAP)r_rLÚdetailrgris& rÚbuild_node_detailršðsÜ ðð ˆó €D÷ ÙØ
!W€FÜðð
ˆó €G÷ ˆŽ B€BØ!Ÿv™vÐ&6Ó7€FÐ ÑØ!Ÿv™v kÓ2€Fˆ;ÑØ!Ÿv™v 2€Fˆ;ÑØ!Ÿv™v 2€Fˆ;ÑØ
Ð×ÔÜÐ/?Õ(@ÈBÔOˆˆä¨{Õ(;ÀrÔJˆˆØ9?À
×9KÔ9Kœ˜v 1°1Ô5ÐQU€Fˆ:ÑÜ%¬I¸wÔG€Fˆ8ÑØ €Mrcóê\4;_uu_4pVPR4VPR4VPR4VP4RRR4R# +'giR#;i)z8Create tables if they don't exist. Runs once at startup.aF
CREATE TABLE IF NOT EXISTS beacon_events (
id INTEGER PRIMARY KEY AUTOINCREMENT, received_at TEXT NOT NULL,
node_id TEXT, node_ts INTEGER, ssid TEXT, bssid TEXT,
rssi INTEGER, channel INTEGER, encryption TEXT, importance TEXT, confidence TEXT