Repository navigation
Releases: NicholasBly/GermGuardianBLE
Release list
v2.0
v2.0
Unrelated side notes: I've successfully ported the Guardian app control over to web bluetooth (Bluefy for iOS, or Chrome/Brave on Android). The only issue is figuring out how to get the pairing/local key using the web version. You'll need to know what your local key is by using this app, connecting to the purifier, and copying it from the settings.
I utilized Claude Opus 5 to help decipher the bluetooth packets using an nRF USB dongle into my PC with Wireshark to intercept the data transmission from my iPhone to the purifier to make web bluetooth work. Download here: #1
Fixed
- White launch flash: launch screen background, splash logo bg, native web-view background, and home-screen base layer were all hard-coded white - now black regardless of theme.
- Startup no longer waits on Guardian's dead cloud server (
_recoverDevicesData) before using the saved local pairing key. - Background/foreground handling rewritten: old
pagehide/resume listeners never fired in WKWebView, so returning to the app didn't refresh status until the next poll (up to 10s later). Now pauses polling in the background and refreshes immediately on return (with a full link reset after >25s away). - Commands sent while the device was mid-read no longer get silently dropped as "busy" - they queue and retry.
- Switching between two paired devices no longer double-stops the wrong device or permanently kills polling.
- Failed commands now revert the UI to the device's real state instead of leaving stale optimistic values.
- Control buttons work immediately instead of only after the first status read completes (up to 8s delay).
Changed
- Script loading:
jquery/hubea/aspe/guardianload via<script defer>in parallel at parse time, not sequentially afterwindow.load. - Server-type probing reduced from a 4-type (
l,p,d,s) x 15s loop to a single 10s try onl(local/offline), since the cloud types are dead. - Device search retry backoff: 500ms → 1s → 2s (was a flat 2s), with a 6s watchdog per attempt so a stuck native callback doesn't hang the search.
- Connection retry delay: 2s → 1s.
- Debug log rewritten as a capped ring buffer (500 lines kept, 200 rendered) with batched DOM flushes; previously unbounded and forced a layout per line.
- Image
srcupdates (air quality, speed, theme icons) now skip the DOM write when the value hasn't changed.
Removed
- Unused bundled assets:
css/,fonts/,locales/,js/crypto-js/, 7 unused JS files, iPad-only app icons, stale_CodeSignature/SC_Info. - iPad support (
UIDeviceFamily→ iPhone-only) and unused background modes (fetch,remote-notification), keeping onlybluetooth-central.
App package size: 3.98 MB → 3.44 MB (installed), IPA 1.53 MB → 1.25 MB.
v1.7
v1.7
New Features
- Added HEPA life and UV Bulb life to the main control page shown as percentages
Optimizations
- Loading time optimizations
- JavaScript code optimizations
- Sending command speed optimizations
Fixes
- Fixed incorrect connection gateway via deviceID, sometimes causing connection to fail with no working controls
- Converted pixel sizing rules to rem for better scalability
v1.6
Skip over getInstallId as it will always time out. Saves 5+ seconds of loading time.
Optimized HTML/CSS
v1.5 - iOS 26.1 Support
Support for iOS 26.1 RC - major changes by Apple broke previous versions.
-
Added javascript logs to main log for more information
-
Patched lots of javascript functions as a work around
-
Patched walkthrough storyboard file to load main storyboard file
-> Info.plist no longer loads the html file due to Apple's 26.1 changes -
Rewrote main connection logic
-> Prioritize local server first, load all scripts from parent directory first = faster load times -
Added "Copy Log" button underneath console log
-
Added Polling Rate modifier 3 - 10 seconds (10 seconds is default)
-
Added Device LocalKey Show & Copy button
-
Added app sleep + resume functionality to fix background battery drain (present in original app)
-> App will disconnect from purifier when app is no longer in focus, stopping it from constantly polling it in the background
-> App might become unstable after resuming. Commands might not send immediately, try restarting the app
v1.4a
Redesigned UI to closely match the original
Functional UI features from original (green/orange/red purifier icon + visual speed bars)
Added dark mode and amoled mode + applicable icons
Moved console log to settings page and loading screen only
CSS adjustments
Removed more unused assets to shrink file size -> ~1.5MB
Planned features for v1.5a / full release:
Javascript optimizations and faster polling for better responsiveness and loading times
v1.3a
-
Added device selector to settings tab (shows if more than one GermGuardian air purifier is detected)
-
Slimmed down .ipa: ~7.5MB -> ~2.5MB
v1.2a
Added Control + Settings Tab
Settings tab now shows HEPA filter and UV-C bulb life
Moved "Dark Mode" and "Show Console Log" to Settings tab
Disabled red warning icon present in top right corner when location is not set to always
Icon file was renamed in order to hide it
Location of file is Payload -> oem4guardiantech.app -> oem4guardiantech-Resources.bundle -> icon_alert.png (now icon_alert_disabled.png)
v1.1a
Bug Fixes:
- Fixed app connecting to the wrong device sometimes.
Explanation:
Stricter Filtering: findDevice and findDeviceDirectly both now explicitly filter the list of detected devices to include only those whose productCode exists and is present in the GUARDIAN_PRODUCT_CODES list.
v1.0a - Initial Release
To do:
-
UI needs some cleanup for a stable release.
-
After saving local pairing key, the app might hang trying to pair with different device id when reopened. Relaunching the app will fix it as a workaround.
-
Create settings page to list air purifier details: power on hours for filter and UV C bulb (visible in console), notification/badge when filter life is EOL.