Typo "wifi.interfaceface" should be "wifi.interface" in the debug
log for the bettercap set wifi.interface command result.
Signed-off-by: PwnPacker <4704376+CoderFX@users.noreply.github.com>
Four robustness improvements to PiSugarServer I2C communication:
1. Race condition: build i2creg into temp list, swap atomically with
threading lock so UI thread never reads partial register data.
2. Bus recovery: add error counter with exponential backoff (3s-30s),
log suppression after 3 errors, and SMBus reconnect after 5
consecutive failures to recover from MCU deep sleep.
3. Write protection: restructure as try/finally so register 0x0B is
always re-enabled even if the middle write fails.
4. Shutdown safety: wrap I2C writes in try/except/finally so failures
are logged but never prevent pwnagotchi.shutdown() from executing.
Fixes#511
Signed-off-by: PwnPacker <4704376+CoderFX@users.noreply.github.com>
For PiSugar2/2Plus with max_charge_voltage_protection enabled,
battery_voltage was appended to voltage_history twice per cycle:
once inside the charge protection block and once unconditionally
at the end. This skews the trimmed-mean battery level calculation.
Make the final append conditional so each model appends exactly
once per cycle regardless of charge protection setting.
Fixes#509
Signed-off-by: PwnPacker <4704376+CoderFX@users.noreply.github.com>
on_loaded crashes with AttributeError when PiSugar is not connected
because it accesses self.ps without a None check. Also uses direct
dict access on self.options which crashes if keys are missing.
on_ui_update crashes when checking battery_plugged outside the
self.ready guard, hitting self.ps.get_battery_power_plugged on None.
Changes:
- Wrap self.ps access in on_loaded with None guard
- Use self.options.get() with safe defaults
- Move battery_plugged inside self.ready + self.ps check
- Downgrade "PiSugar is not ready" from info to debug
Fixes#507
Signed-off-by: PwnPacker <4704376+CoderFX@users.noreply.github.com>
The web UI checks for 'Pisugar 3' (with space, lowercase 's') but
the model detection sets self.model = 'PiSugar3' (no space, uppercase 'S').
This causes 5 PiSugar3-specific fields to never display their actual values.
Replace all occurrences to match the value set during initialization.
Fixes#505
Signed-off-by: PwnPacker <4704376+CoderFX@users.noreply.github.com>
PiSugar 3 users need graceful shutdown with e-ink feedback, boot-loop
prevention when charging from dead battery, and automatic recovery
when pisugar-server loses I2C connection after MCU wake.
- safe-shutdown.sh: stops pwnagotchi, draws sleeping face on e-ink,
powers off. Boot-loop guard skips shutdown when battery <10% and
charging.
- pisugar-watchdog.sh + systemd timer: detects MCU wake from deep
sleep and restarts pisugar-server when I2C is present but daemon
reports disconnected.
- epd-shutdown.py / epd-startup.py: e-ink display faces for
Waveshare V4. Exit silently on non-V4 displays.
Signed-off-by: CoderFX <4704376+CoderFX@users.noreply.github.com>
on_bcap_sys_log fires on every bettercap syslog event matching "wifi
error while hopping to channel". When bettercap is in a bad state, it
sends many such events per second. Each one triggers agent.run() to
flip wifi.recon, which also fails because bettercap is unstable. This
creates a cascade of TypeError errors filling the log — 61 errors in
a few minutes in observed logs.
Two fixes:
1. Safe Message access: use event.get() with isinstance check instead
of direct dict access into re.search(). Prevents TypeError when
Message is None or non-string, and KeyError if event structure is
unexpected.
2. Add 30-second cooldown: check self.LASTTRY before attempting a
recon flip, matching the debounce pattern already used in on_epoch
and _tryTurningItOffAndOnAgain. Update LASTTRY on all outcomes
(success, failure, exception) to prevent cascading retries.
Signed-off-by: CoderFX <4704376+CoderFX@users.noreply.github.com>
The whitelist in config.toml is checked in get_access_points() to
filter APs from active attacks, but bettercap still passively captures
handshakes from all networks including whitelisted ones. The
_on_event() handler processes wifi.client.handshake events without
any whitelist check, so handshakes from the user's own networks are
saved and reported as new captures.
Add whitelist filtering to _on_event() with two checks:
- By MAC address immediately after extracting ap_mac (catches
MAC-based whitelist entries before any processing)
- By hostname after _find_ap_sta_in() resolves the AP (catches
name-based whitelist entries)
When a whitelisted handshake is detected, the pcap file that
bettercap already wrote to disk is removed to prevent accumulation.
Signed-off-by: CoderFX <4704376+CoderFX@users.noreply.github.com>
- Fix interaction display to handle new history dict format
({count, first_seen} from handshake capture optimization PR)
- Escape preset names in HTML output to prevent XSS
- Deduplicate channel list to avoid scanning same channel twice
- Replace deprecated logging.warn() with logging.warning()
- Reduce default extra_channels from 15 to 5 (15 scans nearly all
2.4GHz channels every epoch, defeating focused scanning)
Signed-off-by: CoderFX <153912+CoderFX@users.noreply.github.com>
Signed-off-by: CoderFX <4704376+CoderFX@users.noreply.github.com>
agent.py:
- Fix _has_handshake() substring match bug: was matching partial MACs
(e.g. "AA:BB:CC" matching "AA:BB:CC:DD:EE:FF"), causing APs to be
skipped. Now splits key on ' -> ' and checks exact MAC match.
- Add time-based decay to interaction history: previously once an AP/STA
hit max_interactions it was permanently skipped for the session. Now
resets count after 5 minutes, allowing retry of stubborn targets.
- Cap recon time increase when inactive: was doubling (30s->60s), now
adds at most 15s to avoid long idle periods with fewer channel hops.
- Interleave populated and sparse channels instead of always hitting
most-populated first, giving sparse channels fair coverage.
- Use set for whitelist lookup (O(1) instead of O(n) per AP).
- Remove fragile mac[:13] prefix whitelist match, use full MAC only.
- Add backward compat for recovery data format change.
cli.py:
- Reduce inter-deauth sleep from 1.0s to 0.3s. The 1s delay was overly
conservative for nexmon firmware; 0.3s is sufficient and processes
multi-client APs 3x faster.
Signed-off-by: CoderFX <153912+CoderFX@users.noreply.github.com>
Signed-off-by: CoderFX <4704376+CoderFX@users.noreply.github.com>