Skip to content

shortcuts/pgpemu

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pokemon Go Plus Emulator for ESP32C3

Autocatcher/Gotcha/Pokemon Go Plus device emulator for Pokemon Go, with autospin and autocatch capabilities.

Note

This repository is based on yohane's initial work, spezifisch's fork and paper183's fork.

Warning

This repository doesn't contain the secret blobs needed to make a working emulator for a PGP! You need to dump these secrets yourself from your own original device (see References for some pointers).


Table of Contents

  1. Features
  2. Hardware Requirements
  3. Installation & Setup
  4. Configuration
  5. Usage Guide
  6. Architecture
  7. Project Structure
  8. Code Organization
  9. Testing Guide
  10. Manual Testing Guide
  11. Troubleshooting
  12. Contributing
  13. References

Features

Hardware and Configuration

  • ESP-IDF with BLE support
  • Tailored for ESP32-C3, draws around 0.05A on average
  • Settings menu using serial port
  • Statically loaded secrets (see Load Pokemon Go Plus Secrets) in NVS
  • Toggle autocatch/autospin
  • Android 15+ support

Pokemon Go Plus Features

  • Connect up to 4 different devices simultaneously with independent settings
  • Session key caching - reconnect without passkey after initial pairing
  • Per-device settings - each connected device can have unique configuration
  • LED pattern recognition for multiple scenarios:
    • Pokemon caught
    • Pokemon fled
    • Pokestop spin
    • Bag full
    • Box full
    • Pokeballs empty
  • Retoggle feature - automatically disable/enable autocatch or autospin when certain conditions occur (bag full, box full, etc.)
  • Randomized delays for button press and duration
  • Settings persistence - all settings saved to NVS across reboots
  • pogoplusle - compatible, benefits from auto reconnect and seamless handshake

Hardware Requirements

  • Microcontroller: ESP32-C3
  • ESP-IDF Version: v5.4.1
  • Average Power Draw: ~0.05A
  • Communication Protocol: BLE (Bluetooth Low Energy)
  • Storage: NVS (Non-Volatile Storage) for settings persistence
  • Serial Interface: USB UART for configuration menu

Installation & Setup

Prerequisites

You need ESP-IDF v5.4.1 installed. See the get started with ESP-IDF for ESP32-C3 guide.

Option 1: VSCode with ESP-IDF Extension

  1. Install the VSCode ESP-IDF extension
  2. Open the folder ./pgpemu-esp32 as a new project in VSCode
  3. Configure the extension:
    • Shift+⌘+P > ESP-IDF: Select Port to Use > choose your device (e.g. /dev/tty.usbmodem101)
    • Shift+⌘+P > ESP-IDF: Set Espressif Device Target > esp32c3
    • Shift+⌘+P > ESP-IDF: Select Flash Method > JTAG
    • Shift+⌘+P > ESP-IDF: Build, Flash and Monitor

Option 2: Command Line

cd pgpemu-esp32

# Build the project
idf.py build

# Flash to device (adjust port as needed)
idf.py flash -p /dev/ttyUSB0 -b 921600

# Monitor serial output
idf.py monitor -p /dev/ttyUSB0

Configuration

Load Pokemon Go Plus Secrets

Warning

This fork only allows one secret per flashed device (statically loaded). Other forks allow dynamic secret loading via serial ports, but this implementation prioritizes simplicity and reliability.

Steps

  1. Extract secrets from your original Pokemon Go Plus device (see References)
  2. Rename secrets.example.csv to secrets.csv
  3. Update the values following the schema:
# Secrets options               # this section is for secrets only
key,type,encoding,value         # /!\ do not edit this line
pgpsecret,namespace,,           # /!\ do not edit this line
name,data,string,"PKLMGOPLUS"   # <- the name of your device
mac,data,hex2bin,7c..........   # <- the mac address you've extracted - should be 12 char long
dkey,data,hex2bin,9b.........   # <- the device key you've extracted - should be 32 char long
blob,data,hex2bin,16.........   # <- the blob data you've extracted - should be 512 char long
# Settings options              # this section is for flash-time settings, it can be overridden later from the uart menu
user_settings,namespace,,       # /!\ do not edit this line
catch,data,i8,1                 # enable autocatch - 1 = yes, 0 = no
spin,data,i8,1                  # enable autospin - 1 = yes, 0 = no
spinp,data,u8,0                 # spin probability out of 10, low storage capacity can lead to full bag issues, this allows spinning to be enabled while aiming to reduce chances of full bags - 0 = spin everything, 1 to 9 = N/10
button,data,i8,1                # enable input button on pokemon encounter - 1 = yes, 0 = no
llevel,data,i8,2                # esp monitor log level - 1 = debug, 2 = info, 3 = verbose
maxcon,data,u8,2                # max allowed bluetooth connection to the device, up to 4

After updating secrets.csv, rebuild and flash your device.


Usage Guide

Serial Menu Commands

Help Menu (Press ?)

---HELP---
Secrets: PKLMGOPLUS
User Settings:
- as - toggle autospin
- a[0,9] - autospin probability
- ac - toggle autocatch
- l - cycle through log levels
- S - save user settings permanently
Commands:
- ? - help
- r - show runtime counter
- t - show FreeRTOS task list
- s - show all configuration values
- R - restart
Hardware:
- B - toggle input button
Secrets:
- xs - show loaded secrets
- xr - reset loaded secrets
Bluetooth:
- bA - start advertising
- ba - stop advertising
- bs - show client states
- br - clear connections
- b[1,4] - set maximum client connections (e.g. 3 clients max. with 'b3', up to 4)

View Current Settings (Press s)

---SETTINGS---
- Autospin: on
- Autospin probability: 4
- Autocatch: on
- Input button: on
- Log level: 2
- Connections: 1 / 2

View Runtime Statistics (Press r)

---STATS---
Connection 0:
- Caught: 7
- Fled: 4
- Spin: 0
---STATS---
Connection 1:
- Caught: 35
- Fled: 24
- Spin: 60

View Bluetooth Client States (Press bs)

I (1716661) pgp_handshake: active_connections: 1
I (1716661) pgp_handshake: conn_id_map:
I (1716661) pgp_handshake: 0: ffff
I (1716661) pgp_handshake: 1: ffff
...

Per-Device UART Commands

Format: <device_idx><command>[<value>]

  • <device_idx>: 0-3 for device 0-3
  • <command>:
    • s: Toggle autospin for device
    • c: Toggle autocatch for device
    • p<value>: Set autospin probability (0-9)
    • l: Cycle log level for device

Examples:

0s     → Toggle autospin on device 0
1c     → Toggle autocatch on device 1
2p5    → Set device 2 probability to 50%
0l     → Cycle log level for device 0

Architecture

System Overview

Pokemon GO App (Smartphone)
        ↓
    BLE GATT
        ↓
    ESP32-C3
    ┌───────────────────────────────────────────┐
    │                                           │
    │  BLE GATT Server (pgp_gatts.c)           │
    │  └─ Handles Pokemon Go protocol          │
    │                                           │
    ├─ Connection Management (pgp_handshake_multi.c)
    │  └─ Tracks up to 4 simultaneous devices  │
    │  └─ Session key caching                  │
    │                                           │
    ├─ Settings & Storage (config_storage.c)   │
    │  └─ Per-device settings                  │
    │  └─ Session key persistence              │
    │  └─ NVS (flash storage)                  │
    │                                           │
    ├─ Feature Tasks                            │
    │  ├─ LED Handler (pgp_led_handler.c)      │
    │  ├─ Auto Button (pgp_autobutton.c)       │
    │  └─ Auto Setting (pgp_autosetting.c)     │
    │                                           │
    ├─ Serial Interface (uart.c)               │
    │  └─ Configuration menu                   │
    │                                           │
    └─ System Services                          │
       ├─ Bluetooth GAP (pgp_gap.c)            │
       └─ Statistics (stats.c)                 │
    │
    └─ Serial Monitor (console output)

Critical Data Flow

  1. Connection Establishment:

    • Pokemon Go app scans for PGPemu
    • Initiates BLE GATT connection (pgp_gatts.c)
    • Device handshake (pgp_handshake_multi.c)
    • Full handshake with passkey on first connection (~3-5 seconds)
    • Session key caching to NVS (config_storage.c)
  2. Reconnection:

    • Pokemon Go reconnects to previously paired device
    • Session key retrieved from NVS
    • Expedited handshake (~1 second, no passkey needed)
  3. Settings Management:

    • Each connection tracked by conn_id
    • Per-device DeviceSettings structure in RAM
    • Settings persisted to NVS by device MAC address
    • Settings loaded on device connection
  4. Feature Triggering:

    • LED patterns detected (pgp_led_handler.c)
    • Pattern triggers auto actions (pgp_autobutton.c, pgp_autosetting.c)
    • Retoggle feature temporarily disables/enables features

Key Modules

pgp_handshake_multi.c:18-45

  • Multi-device connection tracking - manages up to 4 simultaneous connections
  • State machine - tracks cert_state, recon_key (reconnect key), notify state
  • Connection mapping - maps BLE connection IDs to device indices
  • Mutual exclusion - protects active_connections counter with mutex

config_storage.c:50-120

  • Session key persistence - reads/writes from NVS by MAC address
  • Device settings storage - FNV-1a hash for key generation
  • NVS helpers - wrapper functions with error checking
  • Mutex protection - settings_mutex for thread-safe access

pgp_gatts.c:100-200

  • GATT characteristic handlers - reads/writes from Pokemon Go
  • Handshake protocol - certificate exchange, key negotiation
  • Notification system - sends data to Pokemon Go

pgp_led_handler.c:30-80

  • LED pattern parsing - recognizes game state from LED colors
  • Action triggers - calls auto functions based on patterns
  • Retoggle queue - schedules setting changes

pgp_autobutton.c & pgp_autosetting.c

  • Automatic actions - simulates button presses, changes settings
  • Per-device settings - operates on specific device's settings
  • Timing logic - randomized delays for natural behavior

Project Structure

pgpemu/
├── pgpemu-esp32/                    # ESP32-C3 Firmware
│   ├── main/
│   │   ├── Core Connection Management:
│   │   │   ├── pgp_handshake_multi.c(.h)    # Multi-device connection tracker
│   │   │   ├── pgp_gatts.c(.h)              # BLE GATT server
│   │   │   └── pgp_handshake.c(.h)          # Encryption/decryption
│   │   │
│   │   ├── Settings & Storage:
│   │   │   ├── config_storage.c(.h)         # NVS persistence, device settings
│   │   │   ├── config_secrets.c(.h)         # Secret management
│   │   │   ├── settings.c(.h)               # Settings logic
│   │   │   └── nvs_helper.c(.h)             # NVS utilities
│   │   │
│   │   ├── Features:
│   │   │   ├── pgp_led_handler.c(.h)        # LED pattern → action
│   │   │   ├── pgp_autobutton.c(.h)         # Button press simulation
│   │   │   ├── pgp_autosetting.c(.h)        # Retoggle feature
│   │   │   └── button_input.c(.h)           # GPIO handler
│   │   │
│   │   ├── Communication:
│   │   │   ├── pgp_bluetooth.c(.h)          # BLE initialization
│   │   │   ├── pgp_gap.c(.h)                # BLE device discovery
│   │   │   ├── pgp_cert.c(.h)               # Certificate handling
│   │   │   └── uart.c(.h)                   # Serial menu interface
│   │   │
│   │   ├── System:
│   │   │   ├── pgpemu.c                     # Main entry point
│   │   │   ├── stats.c(.h)                  # Statistics tracking
│   │   │   └── log_tags.c(.h)               # Log definitions
│   │   │
│   │   └── pc/                              # PC Unit Tests (all tests pass)
│   │       ├── test_regression.c            # 46 assertions - Critical bugs
│   │       ├── test_edge_cases.c            # 76 assertions - Boundaries
│   │       ├── test_error_handling.c        # Error recovery
│   │       ├── test_settings.c              # Settings logic
│   │       ├── test_handshake_multi.c       # Multi-device connections
│   │       ├── test_config_storage.c        # NVS persistence
│   │       ├── test_nvs_helper.c            # NVS utilities
│   │       └── run_tests.sh                 # Test runner script
│   │
│   ├── CMakeLists.txt                       # Build configuration
│   ├── sdkconfig                            # ESP-IDF configuration (v5.4.1)
│   ├── secrets.example.csv                  # Template for device secrets
│   ├── .clang-format                        # Code style configuration
│   ├── .clang-tidy                          # Static analysis rules
│   └── Makefile.test                        # Test compilation rules
│
├── scripts/                                 # Helper scripts
│   ├── monitor.fish                         # Fish shell monitor script
│   └── setup.fish                           # Fish shell setup script
│
├── README.md                                # This file - Single source of truth
├── MANUAL_TESTING_GUIDE.md                  # ⚠️ Deprecated - Content merged into README.md
├── TEST_SUITE_GUIDE.md                      # ⚠️ Deprecated - Content merged into README.md
├── FUNDING.yml                              # GitHub funding info
├── LICENSE                                  # Project license
├── run_tests.sh                             # Root-level test runner
└── Makefile                                 # Root-level build helpers

Code Organization

Layer Architecture

The PGPemu codebase is organized in distinct layers with clear separation of concerns:

1. Hardware Abstraction Layer (HAL)

  • button_input.c - GPIO input handling
  • uart.c - Serial communication
  • Direct interaction with ESP32-C3 hardware

2. Communication Layer

  • pgp_gap.c - BLE device discovery
  • pgp_bluetooth.c - BLE initialization
  • pgp_cert.c - Certificate handling

3. Connection Management Layer

  • pgp_handshake_multi.c - Multi-device tracking
  • pgp_gatts.c - GATT protocol implementation
  • pgp_handshake.c - Encryption/decryption

4. Settings & Storage Layer

  • config_storage.c - NVS operations
  • config_secrets.c - Secret management
  • settings.c - Settings logic
  • nvs_helper.c - NVS utility functions

5. Feature Layer

  • pgp_led_handler.c - LED pattern recognition
  • pgp_autobutton.c - Button automation
  • pgp_autosetting.c - Setting changes (retoggle)

6. System Layer

  • pgpemu.c - Main entry and task initialization
  • stats.c - Statistics collection
  • log_tags.c - Log tag definitions

Module Dependencies

pgpemu.c (main)
  ├─ pgp_bluetooth.c
  │   └─ pgp_gap.c
  │   └─ pgp_gatts.c
  │       ├─ pgp_handshake_multi.c
  │       │   └─ config_storage.c
  │       │       └─ nvs_helper.c
  │       └─ pgp_handshake.c
  │           └─ pgp_cert.c
  │
  ├─ pgp_led_handler.c
  │   └─ pgp_autobutton.c
  │   └─ pgp_autosetting.c
  │       └─ settings.c
  │           └─ config_storage.c
  │
  ├─ uart.c
  │   └─ settings.c
  │   └─ config_secrets.c
  │
  └─ stats.c

Testing Guide

Quick Start

# Run all tests
./run_tests.sh

# Expected output: All 267 assertions pass in ~2 seconds

Test Statistics

Test Module Assertions Coverage Status
test_regression.c 46 Critical bug prevention ✓ PASS
test_edge_cases.c 76 Boundary conditions ✓ PASS
test_settings.c 26 Settings logic ✓ PASS
test_config_storage.c 37 NVS persistence ✓ PASS
test_handshake_multi.c 18 Multi-device connections ✓ PASS
test_nvs_helper.c 23 NVS utilities ✓ PASS
test_error_handling.c 37 Error recovery & resilience ✓ PASS
cert-test.c 4 Certificate validation ✓ PASS
TOTAL 267 100% coverage 100% PASS

Test Coverage Overview

This comprehensive test suite contains 267 total assertions across 8 test modules covering critical functionality, edge cases, error handling, and certificate validation.

Regression Tests (46 assertions) - Critical Bug Prevention

Bug #1: Device Settings Pointer Initialization

  • Issue: read_stored_device_settings() return value wasn't checked
  • Test: Verify return value checking prevents NULL dereference
  • Impact: Critical - prevents crashes on device connect

Bug #2: Settings Mutex Memory Leak

  • Issue: New mutex created but never freed in device settings
  • Test: Track malloc/free counts, verify balanced calls
  • Impact: Critical - prevents memory exhaustion with connections

Bug #3: Race Condition on active_connections

  • Issue: Connection counter modified without mutex protection
  • Test: Verify mutex acquire/release around counter operations
  • Impact: Critical - ensures accurate connection tracking

Bug #5: Uninitialized Retoggle Fields

  • Issue: Device retoggle state fields not initialized to zero
  • Test: Verify all fields initialized to false/0 at startup
  • Impact: High - prevents undefined behavior from garbage values

Bug #6: Invalid MAC Address (BDA) Handling

  • Issue: No validation of device Bluetooth addresses
  • Test: Reject NULL, all-zeros, all-ones MAC addresses
  • Impact: High - prevents operations on malformed addresses

Edge Case Tests (76 assertions) - Boundary Validation

  • Maximum Connections: Accept 1-4 devices, reject 5th
  • Probability Values: Valid 0-9, invalid 10+
  • Timing Boundaries: Handle time 0 and max uint32
  • Array Indices: Valid 0-3, reject negative or 4+
  • NVS Key Length: Valid 1-15 chars, invalid empty or 16+
  • Boolean Toggle Logic: Repeated toggles, NULL handling

Error Handling Tests

  • NVS read errors with defaults
  • malloc failure recovery
  • Mutex creation failures
  • Data validation and sanitization

Running Tests

# Run all tests
./run_tests.sh

# Run specific test module
./run_tests.sh test_regression
./run_tests.sh test_edge_cases
./run_tests.sh test_error_handling

# Manual compilation
cd pgpemu-esp32/main/pc
gcc -o test_regression test_regression.c && ./test_regression
gcc -o test_edge_cases test_edge_cases.c && ./test_edge_cases
gcc -o test_error_handling test_error_handling.c && ./test_error_handling

# Certificate validation test
gcc -o cert-test cert-test.c aes.c && ./cert-test

Test Maintenance

When adding new features:

  1. Run existing tests to verify no regressions
  2. Identify tested boundary values in edge_cases.c
  3. Add new test cases for new edge cases
  4. Update regression tests if feature affects critical paths

When fixing bugs:

  1. Create a regression test in test_regression.c
  2. Document what was broken and how the test catches it
  3. Ensure all 267 assertions pass
  4. Commit with reference to the bug fix

When modifying core logic:

  1. Run full test suite: ./run_tests.sh
  2. Verify your changes are covered by tests
  3. Add edge case tests for new boundary values
  4. Check error handling paths still work

Manual Testing Guide

After PC unit tests pass (all 267 assertions), use these procedures to validate features on actual hardware.

Prerequisites

  • ESP32 device flashed with latest PGPemu firmware
  • Pokemon Go app installed on smartphone
  • Bluetooth-capable smartphone
  • Serial monitor (e.g., idf.py monitor)
  • Optional: 2-4 additional devices for multi-device testing

Part 1: Build & Flash

Step 1: Compile the Project

cd pgpemu-esp32
idf.py build

Watch for compilation errors. Known issues:

  • TickType_t format specifier warnings in pgp_handshake_multi.c (non-critical on ESP32)

Step 2: Flash to Device

idf.py flash -p /dev/ttyUSB0 -b 921600  # Adjust port as needed

Step 3: Monitor Serial Output

idf.py monitor -p /dev/ttyUSB0

Keep this running during all test procedures to observe device behavior.


Part 2: Session Key Persistence Testing

Test 2.1: Single Device Reconnection Without Passphrase

Objective: Verify that a device can reconnect without re-entering the passphrase.

Setup:

  1. Flash device and open serial monitor
  2. Let device boot and show startup logs
  3. Open Pokemon Go app

Procedure:

  1. Initial Connection:

    • Scan for PGPemu in Pokemon Go Bluetooth settings
    • Select PGPemu device (should be named Pokemon Go Plus)
    • Observe serial logs showing successful handshake (approx 3-5 seconds)
    • Connection should establish and device should show "connected" status
  2. Disconnect:

    • In Pokemon Go, disconnect from PGPemu
    • Wait 2 seconds
    • Observe device logs: you should see "connection_stop" message
  3. Reconnect:

    • In Pokemon Go, reconnect to PGPemu (don't scan for new device, select previously paired)
    • DO NOT enter passphrase - device should use cached session key
    • Observe serial logs showing expedited handshake (< 1 second)
    • Connection should establish without passphrase prompt

Expected Outcome:

  • First connection: Full handshake with passphrase, ~3-5 seconds
  • Second connection: Session key reuse, ~1 second, NO passphrase needed
  • Serial output shows:
    [handshake] Attempting to retrieve cached session keys...
    [handshake] Session keys found in NVS, skipping full handshake
    

Pass Criteria: ✓ Device reconnects in <2 seconds without passphrase


Test 2.2: Session Key Persistence Across Power Cycle

Objective: Verify that session keys persist after device power cycle.

Setup:

  1. Complete Test 2.1 successfully
  2. Device should be connected

Procedure:

  1. Establish and Record State:

    • Verify device is connected with cached session key
    • Note the device's MAC address from logs (format: AA:BB:CC:DD:EE:FF)
  2. Power Cycle Device:

    • Disconnect from Pokemon Go
    • Unplug device
    • Wait 5 seconds
    • Plug device back in
    • Wait for device to boot (observe startup logs)
  3. Verify Cache Persistence:

    • Open Pokemon Go
    • Reconnect to PGPemu
    • Should reconnect without passphrase in <2 seconds
    • Check NVS logs showing cache retrieval

Expected Outcome:

  • Session key remains in NVS storage after power cycle
  • Reconnection succeeds without passphrase
  • Serial logs show cache hit after boot

Pass Criteria: ✓ Session persists across power cycles, no passphrase required


Test 2.3: MAC Address Mismatch Detection

Objective: Verify that cached keys are device-specific (MAC-based).

Setup:

  1. Device A flashed and tested (has cached session keys)
  2. Device B (different device, different MAC address) flashed

Procedure:

  1. Attempt Cross-Device Reconnection:

    • Device A previously paired and cached
    • Attempt to use cached key from Device A on Device B (not possible directly, but test MAC isolation)
    • If possible in setup, swap firmware images to verify device isolation
  2. Verify Device B Requires Passphrase:

    • Device B should not have cached keys
    • Should prompt for passphrase on first connection
    • Handshake should be full (~3-5 seconds)

Expected Outcome:

  • Each device maintains independent cache
  • Device MAC address is used to generate cache key
  • Different MACs don't share cached session keys

Pass Criteria: ✓ Devices remain isolated, each requires independent passphrase


Part 3: Per-Device Settings Testing

Test 3.1: Single Device Settings Persistence

Objective: Verify that device settings persist independently.

Setup:

  1. Single device flashed and connected
  2. Serial monitor active

Procedure:

  1. Configure Device Settings via UART:

    • Open serial monitor
    • Send UART command: 0s (toggle autospin for device 0)
    • Observe logs showing toggle and NVS write
    • Send UART command: 0p5 (set autospin probability to 50%)
    • Observe probability set in logs
  2. Disconnect and Reconnect:

    • Disconnect from Pokemon Go
    • Wait 2 seconds
    • Reconnect to Pokemon Go
  3. Verify Settings Loaded:

    • Connected device should show saved autospin state
    • Check serial logs confirming loaded settings
    • Settings should match what was configured in step 1
  4. Modify and Verify Again:

    • Send: 0c (toggle autocatch)
    • Disconnect/reconnect
    • Autocatch state should persist

Expected Outcome:

  • Settings saved to NVS after each UART command
  • Settings loaded when device connects
  • Persists across disconnect/reconnect cycles

Pass Criteria: ✓ All device settings persist independently


Test 3.2: Multi-Device Independent Settings

Objective: Verify that 4 devices can have different settings simultaneously.

Setup:

  1. 4 devices flashed (or simulate with controlled connections)
  2. All devices within range

Procedure:

  1. Initial Configuration:

    • Device 0: Autospin ON, Probability 5
    • Device 1: Autospin OFF, Probability 3
    • Device 2: Autospin ON, Probability 8
    • Device 3: Autospin OFF, Probability 1

    Configure via UART:

    0s  (toggle autospin device 0, becomes ON)
    0p5
    1s  (toggle autospin device 1, becomes OFF)
    1p3
    2p8
    3s  (toggle autospin device 3, becomes OFF)
    3p1
    
  2. Verify Independent Operation:

    • Connect Device 0 to Pokemon Go → autospin ON, prob=5
    • Disconnect, connect Device 1 → autospin OFF, prob=3
    • Each device should show its own settings
    • Check serial logs confirming per-device loading
  3. Simultaneous Multi-Device:

    • Connect up to 4 devices simultaneously to Pokemon Go
    • Each device should operate with its independent settings
    • No cross-contamination of settings between devices

Expected Outcome:

  • Each device slot maintains independent settings
  • Settings loaded correctly when device connects
  • No interference between simultaneous connections

Pass Criteria: ✓ 4 devices operate simultaneously with independent settings


Test 3.3: Settings Isolation After Settings Changes

Objective: Verify toggling one device's settings doesn't affect others.

Setup:

  1. 2+ devices connected
  2. Device 0: Autospin ON
  3. Device 1: Autospin OFF

Procedure:

  1. Record Initial States:

    • Observe device 0 autospin: ON
    • Observe device 1 autospin: OFF
  2. Toggle Device 0:

    • Send UART: 0s (toggle device 0 autospin OFF)
    • Observe: Device 0 now OFF
  3. Verify Device 1 Unchanged:

    • Check device 1 autospin status: should still be OFF
    • Verify logs show no changes to device 1
  4. Toggle Device 1:

    • Send UART: 1s (toggle device 1 autospin ON)
    • Verify device 0 still OFF, device 1 now ON

Expected Outcome:

  • Settings mutations are device-specific
  • No cross-device interference
  • Each device maintains independent state

Pass Criteria: ✓ Settings changes isolated between devices


Part 4: Retoggle Feature Testing

Test 4.1: Bag Full Retoggle (White LED)

Objective: Verify autospin is toggled OFF then ON when bag is full.

Setup:

  1. Device connected to Pokemon Go
  2. Pokemon Go app running with autospin enabled
  3. Fill bag in game (triggers white LED on device)

Procedure:

  1. Normal Operation:

    • Play normally, autospin toggling Pokemon
    • Observe device LED changes
  2. Trigger Bag Full:

    • Collect items until bag is full
    • Pokemon Go app will send bag-full signal
    • Device shows white LED indicator
  3. Observe Retoggle:

    • Device receives LED pattern
    • Autospin toggles OFF (stops catching)
    • After 300ms, autospin toggles back ON
    • Behavior: Device stops catching momentarily, then resumes
    • Check serial logs showing retoggle queue entry/processing

Expected Outcome:

  • White LED triggers autospin OFF → ON sequence
  • 300ms delay between OFF and ON
  • Retoggle only affects the connected device
  • Other devices (if connected) unaffected

Pass Criteria: ✓ Autospin retoggle correctly handles bag full


Test 4.2: Box Full Retoggle (Red Solid LED)

Objective: Verify autocatch is toggled when item box is full.

Setup:

  1. Device connected to Pokemon Go
  2. Autocatch enabled
  3. Fill item box in game

Procedure:

  1. Fill Item Box:

    • Collect items until item box is full
    • Pokemon Go sends box-full signal
    • Device shows red solid LED
  2. Observe Retoggle:

    • Device receives LED pattern
    • Autocatch toggles OFF (stops catching items)
    • After 300ms, autocatch toggles back ON
    • Observe device behavior: stops catching momentarily, resumes
  3. Verify Persistence:

    • Disconnect and reconnect device
    • Retoggle settings should be cleared (not persistent on reconnect)

Expected Outcome:

  • Red solid LED triggers autocatch OFF → ON
  • 300ms delay
  • Only affects current device
  • Retoggle clears after device disconnects

Pass Criteria: ✓ Autocatch retoggle correctly handles box full


Test 4.3: Empty Pokéballs Retoggle (Red Blinking LED)

Objective: Verify autocatch toggles when pokéballs empty.

Setup:

  1. Device connected with autocatch enabled
  2. Use up all pokéballs in game

Procedure:

  1. Empty Pokéballs:

    • Use all pokéballs catching Pokemon
    • Pokemon Go sends pokéballs-empty signal
    • Device shows red blinking LED
  2. Observe Retoggle:

    • Autocatch toggles OFF
    • After 300ms, toggles back ON
    • Behavior: Device stops catching, resumes
  3. Multi-Device Verification:

    • If 2+ devices connected, verify other devices unaffected
    • Only the device receiving the signal retoggle

Expected Outcome:

  • Red blinking LED triggers retoggle
  • Isolated to receiving device
  • Settings return to previous state after 300ms

Pass Criteria: ✓ Pokéballs empty retoggle works correctly


Part 5: Multi-Device Scenario Testing

Test 5.1: Four Devices with Different Settings

Objective: Verify full feature set with 4 devices.

Setup:

  1. 4 devices available
  2. Each configured with unique settings:
    • Device 0: Autospin ON, Autocatch OFF, Prob=2
    • Device 1: Autospin OFF, Autocatch ON, Prob=5
    • Device 2: Autospin ON, Autocatch ON, Prob=8
    • Device 3: Autospin OFF, Autocatch OFF, Prob=0

Procedure:

  1. Configure All Devices:

    0s     # Device 0: autospin ON
    0p2
    1s     # Device 1: autospin OFF
    1c     # Device 1: autocatch ON
    1p5
    2p8
    3s     # Device 3: autospin OFF
    3c     # Device 3: autocatch OFF
  2. Simultaneous Connection:

    • Connect all 4 devices to Pokemon Go simultaneously
    • Verify all connect without passphrase (cached keys)
    • Settings loaded correctly for each
  3. Mixed Operations:

    • Bag fills on Device 0 → only autospin retoggle
    • Pokéballs empty on Device 2 → only autocatch retoggle
    • Verify other devices unaffected
    • Each device operates independently
  4. Disconnect One:

    • Disconnect Device 1
    • Active connections count: 3
    • Remaining devices continue operating
  5. Reconnect:

    • Reconnect Device 1
    • Uses cached session key
    • Settings loaded: autocatch ON, prob=5
    • No passphrase required

Expected Outcome:

  • 4 devices with independent settings
  • All share session persistence feature
  • Retoggle isolated per device
  • Settings survive reconnections

Pass Criteria: ✓ Full feature integration works with 4 devices


Part 6: Edge Cases & Stress Testing

Test 6.1: Rapid Disconnect/Reconnect

Objective: Verify stability during rapid connection cycles.

Procedure:

  1. Connect device
  2. Immediately disconnect (< 1 second)
  3. Immediately reconnect
  4. Repeat 5 times
  5. Observe no crashes or memory leaks

Expected Outcome:

  • Device handles rapid reconnects gracefully
  • No log errors or crashes
  • Session keys not corrupted

Pass Criteria: ✓ Device stable under rapid reconnects


Test 6.2: Connection at Max Capacity

Objective: Verify 4-device limit enforcement.

Procedure:

  1. Connect 4 devices
  2. Attempt to connect 5th device
  3. Observe connection rejection

Expected Outcome:

  • 5th device fails to connect
  • Clear error message in logs
  • Connected 4 devices unaffected

Pass Criteria: ✓ Max connection limit enforced


Test 6.3: Very Long Sessions

Objective: Verify stability over extended runtime.

Procedure:

  1. Connect device
  2. Let device run for 1 hour with normal Pokemon Go usage
  3. Monitor serial logs for errors
  4. Observe NVS operations

Expected Outcome:

  • No memory leaks
  • No NVS corruption
  • Settings remain consistent

Pass Criteria: ✓ Device stable over long sessions


Manual Testing Checklist

Use this checklist to track manual testing progress:

  • Test 2.1: Single device reconnection without passphrase
  • Test 2.2: Session key persistence across power cycle
  • Test 2.3: MAC address mismatch detection
  • Test 3.1: Device settings persistence
  • Test 3.2: Multi-device independent settings
  • Test 3.3: Settings isolation
  • Test 4.1: Bag full retoggle
  • Test 4.2: Box full retoggle
  • Test 4.3: Empty pokéballs retoggle
  • Test 5.1: Four devices with different settings
  • Test 6.1: Rapid disconnect/reconnect
  • Test 6.2: Connection at max capacity
  • Test 6.3: Very long sessions

Troubleshooting

Build Issues

ESP-IDF not found

  • Ensure ESP-IDF v5.4.1 is installed
  • Run: . ~/esp/esp-idf/export.sh to set up environment
  • Check: echo $IDF_PATH should point to esp-idf directory

Compilation errors in pgp_handshake_multi.c

  • TickType_t warnings are non-critical on ESP32
  • These come from FreeRTOS headers and don't affect functionality

Tool not found (gcc, make, etc.)

  • Ensure ESP-IDF tools are in PATH
  • Run: . $IDF_PATH/tools/tools.sh
  • Or use VSCode extension which manages tools automatically

Flash Issues

Device not found

  • Verify USB cable is working (try another port)
  • Check device shows up: ls /dev/tty* or ls /dev/cu.*
  • Ensure correct port is specified: -p /dev/ttyUSB0 (adjust as needed)
  • Try different USB port on computer

Permission denied when flashing

  • Linux/Mac: Add your user to dialout group: sudo usermod -a -G dialout $USER
  • Windows: Run command prompt as administrator
  • Reconnect device after permission changes

Flash timeout

  • Try slower baud rate: -b 115200 (instead of 921600)
  • Ensure power supply can handle device: ~0.05A average
  • Try different USB port (some ports have current limiting)

Connection Issues

Device not appearing in Pokemon Go scan

  • Check serial logs for BLE advertisement messages
  • Run idf.py monitor and look for "advertising" messages
  • Verify Bluetooth is enabled on phone
  • Try restarting Pokemon Go app
  • Check device isn't at max connection limit (use b1 to reset)

Connection fails with passphrase

  • Verify correct passphrase: 000000 (six zeros)
  • Check handshake completes in serial logs (3-5 second timeout)
  • Ensure device isn't in mode with suspended advertising
  • Try unplugging and re-plugging device

Session key not cached

  • Check NVS partition has space (look for NVS error logs)
  • Verify handshake completes fully (don't disconnect during handshake)
  • Look for "persist_device_session_keys" messages in logs
  • Try full NVS erase and re-flash: idf.py erase-flash

Settings not loaded on reconnect

  • Verify device MAC address is correct in logs
  • Check NVS key generation (should be 15 hex characters)
  • Ensure read_stored_device_settings() called on connect
  • Verify NVS partition has settings data (use xs command)

Performance Issues

Device is slow to respond

  • Check log level isn't set to DEBUG (too much logging slows device)
  • Reduce number of simultaneous connections if possible
  • Verify no other tasks are blocking (check with t command)
  • Check power supply voltage (low voltage slows device)

Autocatch/Autospin delayed

  • Verify LED handler task is running (look for LED parse logs)
  • Check retoggle queue isn't stuck (full queue blocks new entries)
  • Ensure probability value is correct (0 = always spin/catch)
  • Check FreeRTOS task list with t command

Retoggle not working

  • Verify LED pattern detection in logs
  • Check retoggle queue has space (try br to clear connections)
  • Ensure autosetting_task is running (look in task list)
  • Verify the correct LED pattern is being detected

Multi-Device Issues

Devices interfere with each other

  • Verify conn_id_map not corrupting (check bs output)
  • Ensure each device has independent DeviceSettings struct
  • Check mutex protects device settings (look for "acquiring mutex" logs)
  • Try reducing max connections (b2 to limit to 2 devices)

One device's settings affect another

  • Confirm device MAC addresses are unique in logs
  • Check NVS keys are generated correctly (should differ per MAC)
  • Verify settings mutex isn't holding lock too long
  • Try clearing all connections (br) and reconnecting

Connection limit not enforced

  • Check max connection setting (use s to view)
  • Verify b[1,4] command works to change limit
  • Look for "max connections reached" message in logs
  • Ensure 5th device actually attempts connection (not blocked elsewhere)

Serial Menu Issues

Serial menu not responding

  • Check baud rate is correct (usually 115200)
  • Try pressing Enter key a few times to wake device
  • Verify correct serial port selected
  • Check terminal emulator isn't in read-only mode
  • Restart device with R command

Commands not recognized

  • Commands are case-sensitive
  • Ensure no extra spaces in command
  • Verify full command sent (e.g., 0p5 not just 0p)
  • Check device is responding to other commands first

Settings not saving

  • Use S command to explicitly save settings
  • Note: Settings auto-save on change, S may not be needed
  • Verify NVS is not full (would prevent writes)
  • Check error messages in logs for NVS failures

Contributing

Code Style

  • Language: C99
  • Formatting: Use clang-format with provided .clang-format config
  • Naming conventions:
    • Functions: snake_case
    • Constants: UPPER_CASE
    • Private functions: prefix with underscore _private_function()
    • Type names: snake_case_t for typedef structs

Before Committing

  1. Run all tests and ensure 100% pass rate:

    ./run_tests.sh
     # Must show: All 267 assertions passed
  2. Format your code:

    cd pgpemu-esp32
    clang-format -i main/*.c main/*.h
  3. Run static analysis:

    clang-tidy main/*.c -- -I./main
  4. Build the project:

    idf.py build
  5. No warnings or errors should appear in build output

Commit Message Format

Use the following format for commit messages:

<type>: <subject>

<body>

<footer>

Types:

  • feat: A new feature
  • fix: A bug fix
  • refactor: Code refactoring without feature changes
  • test: Adding or updating tests
  • docs: Documentation updates
  • chore: Build system, dependencies, etc.

Examples:

feat: Add per-device autocatch probability setting

Add ability to set independent autocatch probability (0-9)
for each connected device. Probabilities are persisted to
NVS and survive power cycles.

Fixes: #45
fix: Prevent NULL dereference in read_stored_device_settings

Check return value from read_stored_device_settings() before
dereferencing the result. This prevents crashes when loading
device settings fails.

Includes regression test to prevent reoccurrence.
test: Add comprehensive test suite with 267 assertions

- test_regression.c: 46 assertions for critical bugs
- test_edge_cases.c: 76 assertions for boundaries
- test_settings.c: 26 assertions for settings logic
- test_config_storage.c: 37 assertions for NVS persistence
- test_handshake_multi.c: 18 assertions for multi-device connections
- test_nvs_helper.c: 23 assertions for NVS utilities
- test_error_handling.c: 37 assertions for error recovery
- cert-test.c: 4 assertions for certificate validation

All tests pass on PC without hardware.

Adding New Features

  1. Identify the layer where your feature belongs (see Code Organization)
  2. Add unit tests first in the appropriate test file
  3. Implement the feature to pass the tests
  4. Run full test suite to ensure no regressions
  5. Update documentation if adding new user-facing functionality
  6. Manual test on hardware following Manual Testing Guide
  7. Commit with proper message following format above

Adding New Settings

  1. Define the setting in settings.c with initialization and toggle logic
  2. Add to DeviceSettings struct in settings.h if per-device
  3. Add persistence to config_storage.c if needs to survive power cycle
  4. Add UART command in uart.c for user configuration
  5. Add test cases in test_settings.c and test_edge_cases.c
  6. Document in serial menu help text (uart.c)
  7. Update Configuration section in this README

References

Pokemon Go Plus Reverse Engineering

ESP-IDF Documentation

Bluetooth Low Energy

Development Tools


License

This project is licensed under LICENSE.

About

Pokemon GO Plus emulator for ESP32-C3

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

 

Languages

  • C 97.9%
  • Shell 1.3%
  • Other 0.8%