Skip to content
forked from yohanes/pgpemu

Pokemon GO Plus emulator using ESP32 (fork)

Notifications You must be signed in to change notification settings

spezifisch/pgpemu

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Pokemon Go Plus Emulator for ESP32

Autocatcher for Pokemon Go.

Note: 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).

Features

This fork adds some features:

  • connect up to 4 different devices simultaneously
  • parse LED patterns to detect Pokemon/Pokestops/bag full/box full/Pokeballs empty/etc. and press button only when needed
  • randomized delay for pressing the button and press duration
  • PGP secrets are stored in ESP32 NVS instead of being compiled in
  • settings menu using serial port
  • secrets upload using serial port (see Upload Secrets)
  • setting: autocatch/autospin on/off
  • setting: periodically turn on WiFi to waste some power so your powerbank doesn't turn off (depends on your powerbank if this works)
  • setting: chose between PGP secrets if you have dumps from multiple PGPs
  • setting: chose target number of client connections (Bluetooth advertising starts again automatically until all clients are connected)
  • store user settings in NVS
  • why not use it together with a fashionable case? :)

Hardware

Tested with:

  • ESP32-WROOM-32 (AZDelivery)

Usage

Build Firmware

You need ESP-IDF. I'm using v4.4 (stable) installed using the VSCode extension. To install it use the Get Started Guide.

Open the folder pgpemu-esp32 in VSCode. Run "ESP-IDF Build, Flash and Monitor".

Upload Secrets

Go to ./secrets, rename secrets.example.yaml to secrets.yaml and edit it with your dumped PGP secrets.

You'll need Python 3.9+ and Poetry. Install dependencies:

poetry install --no-root

Then upload your secrets to your device using:

# Linux: (replace /dev/ttyUSB0 with your ESP's serial tty)
poetry run ./secrets_upload.py secrets.yaml /dev/ttyUSB0

Troubleshooting: If you get serial.serialutil.SerialException: device reports readiness to read but returned no data (device disconnected or multiple access on port?) make doubly sure that your previously opened serial terminal (e.g. ESP-IDF Monitor) is stopped.

Configuration

Serial menu:

I (208804) uart_events: Device: RedPGP
I (208814) uart_events: User Settings (lost on restart unless saved):
I (208814) uart_events: - s - toggle PGP autospin
I (208814) uart_events: - c - toggle PGP autocatch
I (208824) uart_events: - p - toggle powerbank ping
I (208824) uart_events: - l - toggle verbose logging
I (208834) uart_events: - S - save user settings permanently
I (208834) uart_events: Edit values:
I (208844) uart_events: - m... - set maximum client connections (eg. 3 clients max. with 'm3', up to 4)
I (208854) uart_events: - X... - edit secrets (select eg. slot 2 with 'X2!')
I (208864) uart_events: Commands:
I (208864) uart_events: - h,? - help
I (208864) uart_events: - A - start BT advertising again
I (208874) uart_events: - t - show BT connection times
I (208884) uart_events: - C - show BT client states
I (208884) uart_events: - T - show FreeRTOS task list
I (208894) uart_events: - R - restart

Development

From VSCode's Command Palette run "ESP-IDF: Add vscode configuration folder" as described here to get working C/C++ IntelliSense.

Show Case

Catching Pokemon on connection ID 1 while spinning a Stop on connection ID 0:

I (715392) pgp_led: Pokemon in range!
I (715392) button_task: pressing button delay=1918 ms, duration=300 ms, conn_id=1
I (716602) pgp_led: Pokestop in range!
I (717312) button_task: pressing button delay=1595 ms, duration=500 ms, conn_id=0
I (718382) pgp_led: LED pattern total duration: 6450 ms
I (718392) pgp_led: Caught Pokemon after 3 ball shakes.
I (720112) pgp_led: Got items from Pokestop.

Not catching Pokemon:

I (503732) pgp_led: Pokemon in range!
I (503732) button_task: pressing button delay=1198 ms, duration=250 ms, conn_id=1
I (506092) pgp_led: Pokemon fled after 3 ball shakes.

Spinning Pokestops:

I (142841) pgp_led: Pokestop in range!
I (142841) button_task: pressing button delay=1895 ms, duration=300 ms, conn_id=0
I (145851) pgp_led: Got items from Pokestop.

Bag full detection:

I (151681) pgp_led: Pokestop in range!
I (151681) button_task: pressing button delay=2288 ms, duration=350 ms, conn_id=0
W (155031) pgp_led: Can't spin Pokestop. Bag is full.

Connect a second phone:

I (324182) uart_events: starting advertising
I (324192) pgp_bt_gap: advertising start successful
I (356572) pgp_bt_gatts: ESP_GATTS_CONNECT_EVT, conn_id=1, mac=...
...
I (363552) pgp_led: Pokemon in range!
I (363552) button_task: pressing button delay=1217 ms, duration=450 ms, conn_id=1   # <- note that this conn_id=1 is from our second connection
W (365882) pgp_led: Pokeballs are empty or Pokestop went out of range.
I (374712) pgp_led: Pokestop in range!
I (374712) button_task: pressing button delay=1742 ms, duration=500 ms, conn_id=0   # <- all the while autocatch/spin from the first connection are still handled

After connecting a third phone:

I (3241231) pgp_bt_gatts: ESP_GATTS_CONNECT_EVT, conn_id=2, mac=...
...
I (3283731) pgp_led: Pokestop in range!
I (3283731) button_task: pressing button delay=1925 ms, duration=350 ms, conn_id=0
I (3284351) pgp_led: Caught Pokemon after 3 ball shakes.
I (3286761) pgp_led: Pokemon in range!
I (3286761) button_task: pressing button delay=2444 ms, duration=250 ms, conn_id=1
I (3286781) pgp_led: Got items from Pokestop.
I (3290101) pgp_led: Pokemon fled after 1 ball shakes.
I (3290231) pgp_bt_gatts: ESP_GATTS_READ_EVT: state=6, CHAR_BATTERY_LEVEL_VAL
I (3291171) pgp_led: Pokemon in range!
I (3291171) button_task: pressing button delay=1168 ms, duration=250 ms, conn_id=2
I (3292271) pgp_led: New Pokemon in range!
I (3292341) button_task: pressing button delay=1069 ms, duration=500 ms, conn_id=1
I (3293501) pgp_led: Caught Pokemon after 3 ball shakes.
I (3294341) pgp_led: Pokemon fled after 3 ball shakes.
I (3299321) pgp_led: Pokemon in range!
I (3299331) button_task: pressing button delay=1457 ms, duration=250 ms, conn_id=1
I (3300471) pgp_led: Pokestop in range!
I (3300781) button_task: pressing button delay=1148 ms, duration=300 ms, conn_id=2
I (3301651) pgp_led: Caught Pokemon after 3 ball shakes.
I (3302951) pgp_led: Got items from Pokestop.
...
I (3560521) uart_events: Task List:
Task Name       Status  Prio    HWM     Task    Affinity
uart_event_task X       12      688     8       -1
IDLE            R       0       1112    6       1
IDLE            R       0       1008    5       0
powerbank_task  B       10      2408    9       -1
ipc0            B       24      1068    1       0
ipc1            B       24      1060    2       1
esp_timer       S       22      3660    3       0
auto_button_tas B       11      336     10      -1
BTC_TASK        B       19      908     12      0
hciT            B       22      1568    13      0
BTU_TASK        B       20      1900    14      0
btController    B       23      2080    11      0
Tmr Svc         B       1       1568    7       0

Keeping track of multiple connections:

# press 't':
I (183264) pgp_handshake: active_connections: 2
I (183264) pgp_handshake: - conn_id=0 connected for 137310 ms
I (183264) pgp_handshake: - conn_id=1 connected for 91220 ms

# press 'C' to see state tables for all 4 client slots:
I (185944) pgp_handshake: active_connections: 2
I (185944) pgp_handshake: conn_id_map:
I (185944) pgp_handshake: 0: 0000
I (185954) pgp_handshake: 1: 0001
I (185954) pgp_handshake: 2: ffff
I (185954) pgp_handshake: 3: ffff
I (185964) pgp_handshake: client_states:
I (185964) pgp_handshake: 0: conn_id=0, cert_state=6, recon_key=1, notify=1
I (185974) pgp_handshake: timestamps: hs=4368, rc=0, cs=4537, ce=0
I (185984) pgp_handshake: keys:
I (185984) pgp_handshake: 8d 0f 9a 26 9c ed b3 5d 6d 3c e8 83 7d be e1 12 
...
I (186034) pgp_handshake: 1: conn_id=1, cert_state=6, recon_key=1, notify=1
I (186044) pgp_handshake: timestamps: hs=8972, rc=0, cs=9146, ce=0
I (186054) pgp_handshake: keys:
I (186054) pgp_handshake: 9c 81 78 80 ab cf e3 8c 8e a0 b6 6c 7a 85 f8 5f
...
I (186114) pgp_handshake: 2: conn_id=0, cert_state=0, recon_key=0, notify=0
I (186114) pgp_handshake: timestamps: hs=0, rc=0, cs=0, ce=0
I (186124) pgp_handshake: keys:
I (186124) pgp_handshake: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
...
I (186184) pgp_handshake: 3: conn_id=0, cert_state=0, recon_key=0, notify=0
I (186184) pgp_handshake: timestamps: hs=0, rc=0, cs=0, ce=0
I (186194) pgp_handshake: keys:
I (186194) pgp_handshake: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
...

Changing PGP secrets slots:

# press 'X?':
W (1182721) uart_events: Secrets Mode
I (1182721) uart_events: User Commands:
I (1182721) uart_events: - h,? - help
I (1182721) uart_events: - q - leave secrets mode
I (1182731) uart_events: - 0-9 - select secrets slot
I (1182731) uart_events: - ! - activate selected slot and restart
I (1182741) uart_events: - l - list slots
I (1182741) uart_events: - C - clear slot
I (1182751) uart_events: - there are additional commands but they are for use in secrets_upload.py only!

# press 'l':
I (359801) config_secrets: - pgpsecret_0: device=RedPGP mac=7c:bb:8a:...
I (359811) config_secrets: - pgpsecret_1: device=BluePGP mac=7c:bb:8a:...
I (359811) config_secrets: - pgpsecret_2: device=YellowPGP mac=7c:bb:8a:...
I (359821) config_secrets: - pgpsecret_3: (none)
I (359821) config_secrets: - pgpsecret_4: (none)
I (359831) config_secrets: - pgpsecret_5: (none)
I (359831) config_secrets: - pgpsecret_6: (none)
I (359841) config_secrets: - pgpsecret_7: (none)
I (359841) config_secrets: - pgpsecret_8: (none)
I (359851) config_secrets: - pgpsecret_9: (none)

# press '2!':
W (438551) uart_events: slot=2
W (439841) uart_events: SETTING SLOT=2 AND RESTARTING
I (439851) uart_events: closing nvs
I (439851) uart_events: restarting
...
I (1072) PGPEMU: Device: YellowPGP
I (1072) PGPEMU: MAC: 7c:bb:8a:...
I (1072) PGPEMU: Ready.
I (1092) pgp_bt_gap: advertising start successful

Uploading secrets:

$ poetry run ./secrets_upload.py secrets.yaml /dev/ttyUSB0
reading input secrets file
- DeviceSecrets(RedPGP)
- DeviceSecrets(BluePGP)
- DeviceSecrets(YellowPGP)
enter secrets mode
> D (13911) uart_events: uart[0] event:
> D (13911) uart_events: [UART DATA]: 1 bytes
> 
> !
listing current secrets:
I (13921) config_secrets: - pgpsecret_0: (none)
I (13921) config_secrets: - pgpsecret_1: (none)
I (13921) config_secrets: - pgpsecret_2: (none)
I (13931) config_secrets: - pgpsecret_3: (none)
I (13931) config_secrets: - pgpsecret_4: (none)
I (13941) config_secrets: - pgpsecret_5: (none)
I (13941) config_secrets: - pgpsecret_6: (none)
I (13951) config_secrets: - pgpsecret_7: (none)
I (13951) config_secrets: - pgpsecret_8: (none)
I (13961) config_secrets: - pgpsecret_9: (none)

uploading secrets
> W (15981) uart_events: slot=0
> W (15991) uart_events: set=N                     
> W (15991) uart_events: N=[OK]
> W (16001) uart_events: set=M
> W (16011) uart_events: M=[OK]
> W (16011) uart_events: set=K
> W (16021) uart_events: K=[OK]
> W (16031) uart_events: set=B
> W (16061) uart_events: B=[OK]
> I (16071) uart_events: slot=tmp crc=7f454c46
> I (16151) config_secrets: [OK] wrote secrets to slot 0
> W (16081) uart_events: write=1
writing to nvs slot 0 OK
> I (16161) uart_events: slot=0 crc=7f454c46
readback OK

> W (16171) uart_events: slot=1
> W (16181) uart_events: set=N
> W (16181) uart_events: N=[OK]
> W (16191) uart_events: set=M
> W (16201) uart_events: M=[OK]
> W (16201) uart_events: set=K
> W (16211) uart_events: K=[OK]
> W (16221) uart_events: set=B
> W (16251) uart_events: B=[OK]
> I (16261) uart_events: slot=tmp crc=c8350200
> I (16281) config_secrets: [OK] wrote secrets to slot 1
> W (16271) uart_events: write=1
writing to nvs slot 1 OK
> I (16291) uart_events: slot=1 crc=c8350200
readback OK

> W (16301) uart_events: slot=2
> W (16311) uart_events: set=N
> W (16311) uart_events: N=[OK]
> W (16321) uart_events: set=M
> W (16331) uart_events: M=[OK]
> W (16331) uart_events: set=K
> W (16341) uart_events: K=[OK]
> W (16351) uart_events: set=B
> W (16381) uart_events: B=[OK]
> I (16391) uart_events: slot=tmp crc=72616d65
> I (16411) config_secrets: [OK] wrote secrets to slot 2
> W (16401) uart_events: write=1
writing to nvs slot 2 OK
> I (16421) uart_events: slot=2 crc=72616d65
readback OK

listing new secrets:
I (16431) config_secrets: - pgpsecret_0: device=RedPGP mac=7c:bb:8a:...
I (16431) config_secrets: - pgpsecret_1: device=BluePGP mac=7c:bb:8a:...
I (16441) config_secrets: - pgpsecret_2: device=YellowPGP mac=7c:bb:8a:...
I (16441) config_secrets: - pgpsecret_3: (none)
I (16451) config_secrets: - pgpsecret_4: (none)
I (16451) config_secrets: - pgpsecret_5: (none)
I (16461) config_secrets: - pgpsecret_6: (none)
I (16461) config_secrets: - pgpsecret_7: (none)
I (16471) config_secrets: - pgpsecret_8: (none)
I (16481) config_secrets: - pgpsecret_9: (none)
leaving secrets mode
> 
> X
OK!

Credits

References

About

Pokemon GO Plus emulator using ESP32 (fork)

Topics

Resources

Stars

Watchers

Forks

Languages

  • C 96.0%
  • Python 3.6%
  • Other 0.4%