Skip to content

BRP084: Temperature command dropped when mode and temperature are set simultaneously #113

Description

@mhano

BRP084: Temperature command dropped when mode and temperature are set simultaneously (from off to on with temperature)

Summary

When update_settings is called on a BRP084 (firmware 2.8.0+ / dsiot protocol) device with both mode and stemp parameters, the temperature is silently dropped. Only the mode command (e_A002/p_01) is sent to the device — the temperature command (e_3001/p_03) is never constructed or sent. This results in the device powering on with its previously stored temperature rather than the requested temperature.

This does not affect BRP069 devices using the /aircon/ API, where set_control_info correctly includes stemp in the same request as mode and pow.

Environment

  • Home Assistant Container (Docker)
  • pydaikin (bundled with HA)
  • Daikin BRP084C built-in Wi-Fi controllers, firmware 3.6.0
  • 3 x floor console units (FVXM series)
  • Exposed to Apple HomeKit via HA HomeKit Bridge integration

Steps to reproduce

  1. Configure a BRP084 Daikin device in HA via the Daikin AC integration
  2. Expose the climate entity to Apple HomeKit via the HomeKit Bridge integration
  3. Turn the unit off
  4. From Apple Home, set the unit to heat at 19°C (mode + temperature sent simultaneously)
  5. Observe that the unit powers on but at its previously stored temperature (e.g. 22°C), not 19°C

Expected behaviour

The unit should power on in heat mode at 19°C. Both the mode and temperature should be sent to the device.

Actual behaviour

The unit powers on in heat mode but at its previously stored temperature. The temperature command is silently dropped.

Root cause analysis

When HomeKit sends mode and temperature simultaneously, _set_chars receives both values:

Thermostat _set_chars: {'TargetHeatingCoolingState': 1, 'TargetTemperature': 19}

This results in two sequential calls to update_settings:

  1. update_settings({'mode': 'hot'}) — mode only
  2. update_settings({'stemp': '19', 'mode': 'hot'}) — mode + temperature

Both calls construct identical request payloads containing only the mode command. The temperature is never translated into a p_03 parameter:

Call 1 — mode only (correct):

Updating settings: {'mode': 'hot'}
Sending request: {'requests': [{'op': 3, 'pc': {'pn': 'dgc_status', 'pch': [
  {'pn': 'e_1002', 'pch': [{'pn': 'e_A002', 'pch': [{'pn': 'p_01', 'pv': '01'}]}]}
]}, 'to': '/dsiot/edge/adr_0100.dgc_status'}]}

Call 2 — mode + temperature (BUG: temperature dropped):

Updating settings: {'stemp': '19', 'mode': 'hot'}
Sending request: {'requests': [{'op': 3, 'pc': {'pn': 'dgc_status', 'pch': [
  {'pn': 'e_1002', 'pch': [{'pn': 'e_A002', 'pch': [{'pn': 'p_01', 'pv': '01'}]}]}
]}, 'to': '/dsiot/edge/adr_0100.dgc_status'}]}

Note: both requests are identical — e_A002/p_01 (mode) only. The expected e_3001/p_03 (temperature) is absent from the second request.

Comparison: temperature-only works correctly

When temperature is set without a mode change (e.g. adjusting the temperature slider while the unit is already on), the correct payload is generated:

Updating settings: {'stemp': '18'}
Sending request: {'requests': [{'op': 3, 'pc': {'pn': 'dgc_status', 'pch': [
  {'pn': 'e_1002', 'pch': [{'pn': 'e_3001', 'pch': [{'pn': 'p_03', 'pv': '24'}]}]}
]}, 'to': '/dsiot/edge/adr_0100.dgc_status'}]}

This confirms the temperature encoding logic works — it is simply never invoked when mode is also present in the settings dict.

Comparison: BRP069 (/aircon/ API) works correctly

The same operation on a BRP069 device correctly includes both mode and temperature in a single request:

Sending request to aircon/set_control_info with params:
  {'mode': '4', 'pow': '1', 'shum': '0', 'stemp': '19', 'f_rate': '3', 'f_dir': '0'}

The bug is specific to daikin_brp084.py.

Detailed debug logs

Test 1: HomeKit automation sets heat + 19°C (temperature dropped)

Unit was previously set to 20°C and turned off.

22:40:21.183 [homekit.type_thermostats] Thermostat _set_chars: {'TargetTemperature': 20, 'TargetHeatingCoolingState': 1}
22:40:21.184 [pydaikin.daikin_brp084] Updating settings: {'mode': 'hot'}
22:40:21.184 [pydaikin.daikin_brp084] Sending request: {... 'e_A002' ... 'p_01': '01' ...}
22:40:21.186 [pydaikin.daikin_brp084] Updating settings: {'stemp': '20', 'mode': 'hot'}
22:40:21.186 [pydaikin.daikin_brp084] Sending request: {... 'e_A002' ... 'p_01': '01' ...}
                                       ^^^ BUG: identical to above, no p_03 temperature

Result: unit powered on at its stored temperature, not 20°C.

Test 2: Manual temperature change (works correctly)

22:38:10.841 [homekit.type_thermostats] Thermostat _set_chars: {'TargetTemperature': 18}
22:38:10.841 [pydaikin.daikin_brp084] Updating settings: {'stemp': '18'}
22:38:10.841 [pydaikin.daikin_brp084] Sending request: {... 'e_3001' ... 'p_03': '24' ...}
                                       ^^^ CORRECT: temperature command sent

Result: unit temperature changed to 18°C as expected.

Probable location of bug

In daikin_brp084.py, the method that constructs the dsiot request payload appears to check for the presence of mode in the settings dict and builds only the mode command (e_A002/p_01), ignoring stemp when both are present. When stemp is the only key, it correctly builds the temperature command (e_3001/p_03).

Workaround

An HA automation that listens for call_service events on climate.set_temperature, captures the requested temperature at trigger time, waits for the polling burst to settle, then re-sends the temperature as a standalone command (which correctly generates the p_03 payload):

alias: Re-push temperature for BRP084 devices
description: >-
  Workaround for pydaikin bug where temperature is dropped when mode and
  temperature are set simultaneously on BRP084 (dsiot) devices
mode: queued
trigger:
  - platform: event
    event_type: call_service
    event_data:
      domain: climate
      service: set_temperature
condition:
  - condition: template
    value_template: "{{ trigger.event.context.parent_id is none }}"
  - condition: template
    value_template: >-
      {{ trigger.event.data.service_data.entity_id in [
        'climate.your_brp084_unit_1',
        'climate.your_brp084_unit_2'
      ] }}
variables:
  target_temp: "{{ trigger.event.data.service_data.temperature }}"
  target_entity: "{{ trigger.event.data.service_data.entity_id }}"
action:
  - delay: 6
  - service: climate.set_temperature
    target:
      entity_id: "{{ target_entity }}"
    data:
      temperature: "{{ target_temp }}"

Key design decisions:

  • context.parent_id is none prevents infinite loops — HomeKit-originated events have no parent context, while the automation's own re-sent command will have a parent_id linking back to this automation.
  • mode: queued ensures multiple units triggered simultaneously are all corrected sequentially.
  • 6-second delay allows the post-command polling burst (typically 2-3 seconds) to settle before sending the temperature-only command.
  • Entity ID filter restricts to BRP084 devices only, since BRP069 devices using the /aircon/ API are not affected.

Impact

Any HomeKit, automation, or API call that sets mode and temperature simultaneously on a BRP084 device will silently drop the temperature. The device will report success and HomeKit/HA will show the requested temperature, but the physical device will be running at its previously stored temperature. This is particularly problematic for scheduled automations (e.g. morning heating schedules) where the discrepancy may go unnoticed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions