A personal-use iOS app to monitor and control a PAX 3 vaporizer over Bluetooth. Built with SwiftUI + CoreBluetooth.
Disclaimer: Independent personal tool. Not affiliated with, endorsed by, or connected to PAX Labs. PAX® is a registered trademark of PAX Labs. This app contains no PAX branding, logos, or proprietary assets.
https://buymeacoffee.com/selfmeister
- A Mac running macOS 13 or later
- Xcode (free, from the Mac App Store — it's a large download, ~10 GB, give it time)
- An iPhone or iPad with Bluetooth, running iOS 16 or later
- A free Apple ID (the one you already use for the App Store is fine)
- A PAX 3
- Go to https://github.com/selfmeister/P3-VapeControl
- Click the green Code button → Download ZIP
- Open the downloaded ZIP — it will create a folder called
P3-VapeControl-mainon your Mac (usually in Downloads)
- Open the
P3-VapeControl-mainfolder - Double-click
PaxController.xcodeproj— Xcode will open
Xcode needs your Apple ID to install apps on your own phone. This is free and does not require a paid developer account.
- In Xcode, open the menu: Xcode → Settings → Accounts
- Click the + button at the bottom left → Add Apple ID
- Sign in with your regular Apple ID and password
- In Xcode, click on PaxController in the left sidebar (the top blue icon)
- In the main area, click on the PaxController target under "TARGETS"
- Click the Signing & Capabilities tab
- Under Team, click the dropdown and select your name / Apple ID
- Xcode will automatically handle the rest
If you see a bundle identifier error, just change
me.personal.PaxControllerto something unique likecom.yourname.paxcontrollerin the Bundle Identifier field.
- Plug your iPhone into your Mac with a USB cable
- Unlock your iPhone and tap Trust if prompted
- In Xcode, click the device selector at the top (it may say "Any iOS Device" or a simulator name)
- Select your iPhone from the list
- Press ⌘R (or click the ▶ Play button in the top left of Xcode)
- Xcode will build the app and install it on your phone — this takes a minute the first time
- The app will launch on your iPhone automatically
The first time you run a sideloaded app, iOS will block it until you trust it:
- On your iPhone, go to Settings → General → VPN & Device Management
- Tap your Apple ID under "Developer App"
- Tap Trust "your Apple ID" → Confirm
Now open the app — it's ready to use.
⚠️ The app must be built from a Mac with Xcode. It cannot run in the iOS Simulator because Bluetooth is not available there.
- Power on your PAX 3 — press and hold the button until it vibrates
- Open the app and go to the Scan tab
- Tap Scan — your PAX 3 should appear within a few seconds
- Tap Connect next to your device
Switch to the Device tab to see:
- Battery level
- Heating state (Off / Standby / Heating / Ready / Cooling / Boost)
- Current oven temperature
- Target temperature
- Lock state, serial number, firmware version
Tap ↺ (top right) to manually refresh.
Tap one of the four preset buttons in the Device tab: 180°C · 193°C · 204°C · 215°C
The Log tab shows a full trace of every Bluetooth packet sent and received — useful if something isn't working.
| Problem | Solution |
|---|---|
| Device not found during scan | Make sure PAX is powered on and not already connected to another app |
Temperatures show -- |
Tap ↺ to refresh after connecting |
| "No team" error in Xcode | Complete Step 3 and 4 above — sign in with your Apple ID |
| "Could not launch" on iPhone | Complete Step 7 — trust the developer certificate |
| Build fails: CommonCrypto not found | In Xcode Build Settings, verify SWIFT_OBJC_BRIDGING_HEADER points to PaxController/Sources/PaxController-Bridging-Header.h |
| App crashes immediately | Use a real device, not the Simulator |
This app only reads device telemetry and sets the heater temperature to standard preset values — the same values available in the official app. It does not touch firmware, disable thermal limits, or override any safety cutoffs.
No data leaves your device. No network requests are made.
PaxController/
├── Sources/
│ ├── PaxControllerApp.swift Entry point (@main)
│ ├── PaxProtocol.swift UUIDs, message types, AES crypto, packet codec
│ ├── BluetoothManager.swift CoreBluetooth central manager + state machine
│ ├── ContentView.swift Root tab view
│ ├── ScanView.swift Device scanning & connection UI
│ ├── DeviceView.swift Status display + temperature control
│ ├── DebugConsoleView.swift In-app BLE log viewer
│ └── PaxController-Bridging-Header.h CommonCrypto bridge
└── Resources/
└── Info.plist Bluetooth permission strings
BluetoothManager— single@MainActorObservableObjectdriving all CoreBluetooth callsPaxProtocol.swift— fully isolated: all crypto, UUIDs, message types, packet encode/decode- Encryption — AES-128 ECB (key derivation) + AES-128 OFB (packet encryption) via CommonCrypto bridging header
- No SPM/CocoaPods dependencies