feat: add Cosori Dual Blaze (CAF-P583S) air fryer support#517
Open
RedsGT wants to merge 6 commits into
Open
Conversation
Registers CAF-P583S-KUS and CAF-P583S-KEU using the existing VeSyncTurboBlazeFryer class -- same bypassV2 protocol (startCook / endCook / getAirfryerStatus). Enables remote start, stop, and status polling out of the box. Default AirFry preset; the device's other 10 presets (Broil, Roast, Bake, Reheat, Steak, Seafood, Veggies, French Fries, Frozen, Chicken) are added in a follow-up commit. Notes: - Dual Blaze has no preheat function (only RESUMABLE feature flag set) - Temperature range 175-400F per the manual - Status map adds standby/preheating/keeping which the device emits 🤖 This commit was authored with assistance from Claude (Anthropic). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds the full set of cooking presets exposed by the VeSync app for the
Cosori Dual Blaze (CAF-P583S):
Recipe IDs from packet captures of the official VeSync app:
Air Fry 14 Broil 17 Roast 13
Bake 9 Reheat 16 Steak 1
Seafood 3 Veggies 15 French Fries 6
Frozen 5 Chicken 2
Default temperature/time per the CAF-P583S-KUS user manual.
New AirFryerCookModes enum values:
STEAK, SEAFOOD, VEGGIES, FRENCH_FRIES, CHICKEN
The CAF-P583S device_map entry now wires up all 11 modes via cook_modes.
Air Fry (id 14) was already defined in AirFryerPresets and is reused as
the default preset.
🤖 This commit was authored with assistance from Claude (Anthropic).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The bypassV2 payload_method was misspelled as 'getAirfyerStatus' (missing 'r' between 'f' and 'y'), causing VeSync's cloud to return 'Invalid bypass parameter' (code 11000000) on every status poll. The fixture in src/tests/api/vesynckitchen/CAF-DC601S.yaml mirrored the same typo, which is why tests passed despite the bug. This affects status polling for all TurboBlaze-class fryers (CAF-DC601S and CAF-P583S).
The TurboBlaze cook-request dataclass had three bugs that prevented set_mode_from_recipe from ever succeeding — including for the existing CAF-DC601S, not just CAF-P583S: 1. Missing 'mode' field. _build_cook_request() sets cook_req['mode'] = recipe.cook_mode, but FryerTurboBlazeRequestData had no such field, so from_dict() rejected it with 'Serialized dict has keys that are not defined: mode'. 2. startAct typed as list[FryerTurboBlazeStartActItem] but _build_cook_request() always passes a single dict, not a list. Type mismatch on deserialization. 3. hasPreheat declared required but only set when recipe.preheat_time is truthy. Most presets (Air Fry, Broil, etc.) have no preheat time, so from_dict() would fail with 'missing required field'. Also adds hasLinkage: bool = False to match the wire payload shape that the VeSync mobile app (and the older WFON patch from mikealanni's PR webdjoe#477 workaround) sends. The cloud may or may not require it, but including it costs nothing and matches a known-good known-working request. This change is what makes 'remote start verified' actually verifiable on the new code path. Without it, no TurboBlaze can start a cook through set_mode_from_recipe.
On TurboBlaze fryers (CAF-DC601S, CAF-P583S Dual Blaze), the
'readyStart' field in the bypassV2 startCook payload has semantics
that are the inverse of what the name suggests:
readyStart=true -> device enters 'ready' state, beeps, and waits
for the user to physically press the Start
button before actually cooking.
readyStart=false -> device begins cooking immediately on receipt.
Live debug from a Dual Blaze (CAF-P583S-KUS) firmware v1.0.15:
startCook with readyStart=true returns code=0/message=Success, but
the subsequent getAirfryerStatus shows cookStatus='ready' rather
than 'cooking', and the device never progresses past the beep until
a physical button press.
mikealanni's working WFON workaround (issue webdjoe#477) used
readyStart=false and that succeeded as true remote-start, which
this commit aligns the upstream code with.
If a downstream consumer eventually wants the 'stage and prompt'
behavior, the recipe dataclass can grow a 'ready_start: bool' field
with a default of False.
The bypassV2 getAirfryerStatus endpoint reports currentTemp (the hardware sensor reading) in Celsius regardless of the response's tempUnit field, which only governs the echoed cookTemp and preheatTemp values. Consumers comparing cook_temp (the cook setpoint, in tempUnit) against current_temp would see false discrepancies — e.g., during a 360 F cook on a US (tempUnit=f) fryer, currentTemp climbs from ~70 (= room temp in C) through the cook range, hitting ~182 at the setpoint (= 360 F in C), which downstream code interprets as 182 F and badly misreports. Live evidence from a CAF-P583S-KUS firmware v1.0.15 cook at 360 F: cookTemp: 360 tempUnit: 'f' currentTemp progression: 155, 160, 165, 170, 172, 177, 182, 184 (clearly Celsius — plateaus at ~setpoint in C, not F) In get_details, convert currentTemp from C to F when resp_model.tempUnit == 'f'. For tempUnit == 'c', pass through unchanged (already in the right unit). This affects the existing CAF-DC601S TurboBlaze identically; that integration's current_temp readings were almost certainly mislabeled too, just less obvious without a setpoint to compare against.
webdjoe
reviewed
May 23, 2026
| return models.FryerTurboBlazeRequestData.from_dict(cook_req) | ||
|
|
||
| async def get_details(self) -> None: | ||
| resp = await self.call_bypassv2_api(payload_method='getAirfyerStatus') |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds support for the Cosori Dual Blaze 6.8qt smart air fryer
(CAF-P583S-KUS / CAF-P583S-KEU). Resolves the request in #477.
The Dual Blaze is a single-chamber model with dual heating elements
that uses the same bypassV2 protocol as TurboBlaze (
startCook,endCook,getAirfryerStatus), so it can reuseVeSyncTurboBlazeFryerwithout needing a new device class.
Commits
device_map.py(basic support, defaultAirFry preset).
packet captures of the official VeSync app, default temp/time per
the CAF-P583S-KUS user manual.
Tested on
currentTemp, cookSetTemp, totalTimeRemaining, stepArray), all 11
presets accepted by the device
Notes
🤖 The patches in this PR were authored with assistance from Claude
(Anthropic).