π§ Troubleshooting & API notes
Which fan parameters are confirmed against the API versus provisional assumptions, and how to probe the rest with `duux debug`.
The Duux Whisper Flex 2's cloud API isn't fully documented. duux-cli's parameter model (src/lib/params.ts) is pinned as a single source of truth, and most of it is now confirmed against a physical fan β this page is an honest account of what's settled versus what's still an assumption, and how to move the rest into "confirmed" yourself.
What's confirmed
- Speed: 1β30. Confirmed by the API spec, and enforced by
@kud/duux's own command builder β sending a speed outside that range throws aRangeErrorbefore a request is even made. - Mode:
normal/natural. Nothing else. The fan has exactly two modes; night is a separate toggle, not a third mode (see below). Driven directly from@kud/duux's own mode enumeration, so widening it there flows through here with no CLI change needed. - Horizontal oscillation (
horosc) is a 0β3 sweep-angle preset, not a boolean.0off,1= 30Β°,2= 60Β°,3= 90Β°. It was modelled as a plain toggle until this was confirmed, which made presets 2 and 3 unreachable. - Vertical oscillation (
verosc) is a 0β2 tilt preset.0off,1= 45Β°,2= 100Β°. - Night mode (
night) is readable, not write-only. The fan reports anightfield in its state alongside everything else, so both the TUI's Night mode row andduux statusshow its real value rather than an unknown placeholder. - Child lock (
lock) is readable and settable. It has its own row in the TUI and its own line induux status. - Commands are addressed by the fan's MAC address, not its numeric sensor id.
duux discoverrecords the MAC for exactly this reason; a fan saved before this was fixed will fail obscurely until you runduux discoveragain. - State comes from
v5/smarthome/sensors, read as each device'slatestData.fullData. There's no working per-device status endpoint β this is the one placegetStatus()and the session both read from. - Battery level and charging state are reported when the optional battery pack is fitted; otherwise
duux statusshows no battery line at all.
What's still provisional
- The timer's 24-hour ceiling is a UI assumption, not an API limit. The spec only says "hours" as a non-negative integer, with no documented upper bound. 24 was picked as a sane default for the range control's maximum β it is not a value the API is known to reject above.
Probing an assumption with duux debug
duux debug exists specifically to test cases like the one above. It sends a raw command string straight to the fan, bypassing the CLI's typed builders β so it can send a value the normal controls would refuse, like a timer past the current ceiling:
duux debug "tune set timer 30"The fan's full reported state is printed immediately after, so you can see directly whether it accepted the value, clamped it, or rejected it. If you confirm the timer accepts more than 24 hours, the fix is a one-line change to TIMER.max in src/lib/params.ts, with the comment above it updated from provisional to confirmed.
Common issues
"Not signed in to Duux. Run the login flow first." β no stored auth metadata. Run duux auth.
"No Duux credentials found in the Keychain for <email>. Run the login flow again." β the config file references an account, but its token isn't in the Keychain (e.g. after a Keychain reset or migrating machines). Run duux auth to sign in again.
"Duux session has expired. Run the login flow again." β the stored token's expiry has passed. Run duux auth to refresh it.
"Not_Allowed" from the cloud. The old blanket refusal from Cloudgarden's status and command endpoints. Rare now that commands are addressed by MAC correctly, but if it does show up, run duux discover to refresh the fan's address, or duux doctor to check your whole setup.
duux status reports a connection failure β it prints the config file path (~/.config/duux/config.json) alongside the error so you can confirm which account and device are active before digging further. duux doctor walks the same account/fan/control-path chain and names the single next thing to fix.