astrandb / miele

A modern integration for Miele devices in Home Assistant
MIT License
205 stars 30 forks source link

Struggling to start a program from HA #584

Open blacknell opened 3 days ago

blacknell commented 3 days ago

The problem

I'm calling the program action to start an ECO wash but it's consistently failing with 400

action: miele.set_program
target:
  device_id:
    - **REDACTED**
data:
  programId: 200
Failed to perform the action miele.set_program. Service set_program: 400 Bad Request

I noted in the log that ECO was program id 200 and also in swagger I retrieved a list of programs. 200 was in the list but did not have a localised name.

Version of miele integration having the issue?

2024.11.0

Version of Home Assistant Core having the issue?

2024.11.1

Anything in the logs that might be useful for us?

Logger: homeassistant.components.websocket_api.http.connection
Source: components/websocket_api/connection.py:315
integration: Home Assistant WebSocket API (documentation, issues)
First occurred: 07:07:38 (5 occurrences)
Last logged: 07:15:46

[546507559056] Error handling message: Service set_program: 400 Bad Request (home_assistant_error) Paul from 192.168.1.13 (Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36)

Additional information

No response

blacknell commented 2 days ago

Here's my diagnostic download while program was running

{
  "home_assistant": {
    "installation_type": "Home Assistant OS",
    "version": "2024.11.1",
    "dev": false,
    "hassio": true,
    "virtualenv": false,
    "python_version": "3.12.4",
    "docker": true,
    "arch": "aarch64",
    "timezone": "Europe/London",
    "os_name": "Linux",
    "os_version": "6.6.31-haos-raspi",
    "supervisor": "2024.11.2",
    "host_os": "Home Assistant OS 13.2",
    "docker_version": "27.2.0",
    "chassis": "embedded",
    "run_as_root": true
  },
  "custom_components": {
    "hacs": {
      "documentation": "https://hacs.xyz/docs/configuration/start",
      "version": "2.0.1",
      "requirements": [
        "aiogithubapi>=22.10.1"
      ]
    },
    "extended_openai_conversation": {
      "documentation": "https://github.com/jekalmin/extended_openai_conversation",
      "version": "1.0.3",
      "requirements": [
        "openai~=1.3.8"
      ]
    },
    "octopus_energy": {
      "documentation": "https://bottlecapdave.github.io/HomeAssistant-OctopusEnergy",
      "version": "13.1.1",
      "requirements": []
    },
    "auto_backup": {
      "documentation": "https://github.com/jcwillox/hass-auto-backup",
      "version": "1.5.1",
      "requirements": []
    },
    "miele": {
      "documentation": "https://github.com/astrandb/miele",
      "version": "2024.11.0",
      "requirements": [
        "flatdict==4.0.1",
        "pymiele==0.1.7"
      ]
    },
    "rpi_gpio": {
      "documentation": "https://github.com/thecode/ha-rpi_gpio",
      "version": "2024.10.2",
      "requirements": [
        "gpiod>=2.2.1"
      ]
    },
    "frigate": {
      "documentation": "https://github.com/blakeblackshear/frigate",
      "version": "5.4.0",
      "requirements": [
        "pytz"
      ]
    },
    "better_thermostat": {
      "documentation": "https://github.com/KartoffelToby/better_thermostat",
      "version": "1.6.1",
      "requirements": []
    }
  },
  "integration_manifest": {
    "domain": "miele",
    "name": "Miele",
    "codeowners": [
      "astrandb"
    ],
    "config_flow": true,
    "dependencies": [
      "application_credentials",
      "http"
    ],
    "documentation": "https://github.com/astrandb/miele",
    "homekit": {},
    "integration_type": "hub",
    "iot_class": "cloud_push",
    "issue_tracker": "https://github.com/astrandb/miele/issues",
    "loggers": [
      "pymiele"
    ],
    "requirements": [
      "flatdict==4.0.1",
      "pymiele==0.1.7"
    ],
    "ssdp": [],
    "version": "2024.11.0",
    "zeroconf": [
      "_mieleathome._tcp.local."
    ],
    "is_built_in": false,
    "overwrites_built_in": false
  },
  "setup_times": {
    "null": {
      "setup": 0.00013884998043067753
    },
    "01JC07H1PJKZ8M30F7V72F8YR8": {
      "wait_import_platforms": -0.3252999930118676,
      "wait_base_component": -0.004533373983576894,
      "config_entry_setup": 5.224419377016602
    }
  },
  "data": {
    "info": {
      "manufacturer": "Miele",
      "model": "G7191"
    },
    "data": {
      "ident|type|key_localized": "Device type",
      "ident|type|value_raw": 7,
      "ident|type|value_localized": "Dishwasher",
      "ident|deviceName": "",
      "ident|protocolVersion": 4,
      "ident|deviceIdentLabel|fabNumber": "**REDACTED**",
      "ident|deviceIdentLabel|fabIndex": "75",
      "ident|deviceIdentLabel|techType": "G7191",
      "ident|deviceIdentLabel|matNumber": "12469660",
      "ident|deviceIdentLabel|swids|0": "6143",
      "ident|deviceIdentLabel|swids|1": "20700",
      "ident|deviceIdentLabel|swids|2": "25479",
      "ident|deviceIdentLabel|swids|3": "25480",
      "ident|deviceIdentLabel|swids|4": "25499",
      "ident|deviceIdentLabel|swids|5": "25554",
      "ident|deviceIdentLabel|swids|6": "6142",
      "ident|deviceIdentLabel|swids|7": "20475",
      "ident|deviceIdentLabel|swids|8": "25266",
      "ident|xkmIdentLabel|techType": "EK057",
      "ident|xkmIdentLabel|releaseVersion": "08.23",
      "state|ProgramID|value_raw": 200,
      "state|ProgramID|value_localized": "",
      "state|ProgramID|key_localized": "Program name",
      "state|status|value_raw": 5,
      "state|status|value_localized": "In use",
      "state|status|key_localized": "status",
      "state|programType|value_raw": 1,
      "state|programType|value_localized": "Program",
      "state|programType|key_localized": "Program type",
      "state|programPhase|value_raw": 1799,
      "state|programPhase|value_localized": "Drying",
      "state|programPhase|key_localized": "Program phase",
      "state|remainingTime|0": 1,
      "state|remainingTime|1": 0,
      "state|startTime|0": 0,
      "state|startTime|1": 0,
      "state|targetTemperature|0|value_raw": -32768,
      "state|targetTemperature|0|value_localized": null,
      "state|targetTemperature|0|unit": "Celsius",
      "state|targetTemperature|1|value_raw": -32768,
      "state|targetTemperature|1|value_localized": null,
      "state|targetTemperature|1|unit": "Celsius",
      "state|targetTemperature|2|value_raw": -32768,
      "state|targetTemperature|2|value_localized": null,
      "state|targetTemperature|2|unit": "Celsius",
      "state|coreTargetTemperature|0|value_raw": -32768,
      "state|coreTargetTemperature|0|value_localized": null,
      "state|coreTargetTemperature|0|unit": "Celsius",
      "state|temperature|0|value_raw": -32768,
      "state|temperature|0|value_localized": null,
      "state|temperature|0|unit": "Celsius",
      "state|temperature|1|value_raw": -32768,
      "state|temperature|1|value_localized": null,
      "state|temperature|1|unit": "Celsius",
      "state|temperature|2|value_raw": -32768,
      "state|temperature|2|value_localized": null,
      "state|temperature|2|unit": "Celsius",
      "state|coreTemperature|0|value_raw": -32768,
      "state|coreTemperature|0|value_localized": null,
      "state|coreTemperature|0|unit": "Celsius",
      "state|signalInfo": false,
      "state|signalFailure": false,
      "state|signalDoor": false,
      "state|remoteEnable|fullRemoteControl": true,
      "state|remoteEnable|smartGrid": false,
      "state|remoteEnable|mobileStart": true,
      "state|ambientLight": null,
      "state|light": null,
      "state|elapsedTime|0": 2,
      "state|elapsedTime|1": 23,
      "state|spinningSpeed|unit": "rpm",
      "state|spinningSpeed|value_raw": null,
      "state|spinningSpeed|value_localized": null,
      "state|spinningSpeed|key_localized": "Spin speed",
      "state|dryingStep|value_raw": null,
      "state|dryingStep|value_localized": "",
      "state|dryingStep|key_localized": "Drying level",
      "state|ventilationStep|value_raw": null,
      "state|ventilationStep|value_localized": "",
      "state|ventilationStep|key_localized": "Fan level",
      "state|plateStep": {},
      "state|ecoFeedback|currentWaterConsumption|unit": "l",
      "state|ecoFeedback|currentWaterConsumption|value": 8.0,
      "state|ecoFeedback|currentEnergyConsumption|unit": "kWh",
      "state|ecoFeedback|currentEnergyConsumption|value": 0.7,
      "state|ecoFeedback|waterForecast": 0.1,
      "state|ecoFeedback|energyForecast": 0.3,
      "state|batteryLevel": null
    },
    "actions": {
      "processAction": [
        2
      ],
      "light": [],
      "ambientLight": [],
      "startTime": [],
      "ventilationStep": [],
      "programId": [],
      "targetTemperature": [],
      "deviceName": true,
      "powerOn": false,
      "powerOff": true,
      "colors": [],
      "modes": [],
      "runOnTime": []
    },
    "programs": {
      "code": 400,
      "message": "Device **REDACTED** is not in the correct state."
    },
    "id_log": [],
    "local_mappings": {}
  }
}
astrandb commented 2 days ago

Thank you @blacknell, The key info is at the bottom of the diagnostic file:

    "programs": {
      "code": 400,
      "message": "Device 000200820346 is not in the correct state."
    },

The sequence of actions needed to start a program is varying slightly between appliance types and models and is is not documentet anywhere by Miele so you will have to experiment. A typical approach is to set the device in Power on and enable remote start manually (MobileStart, MobileControl) and (and close the door). You can the issue the service call. The avaliable program id:s can be listed by the GET programs endpoint in Swagger when the device is in remote control state. You can do that once and save the result for future use.

blacknell commented 2 days ago

I have tried a lot of experimentation and the program does require MobileStart to be enabled on the machine. If you turn the machine on and then close the door it immediately starts the default program - so my G7191 must be slightly different.

I think the error you highlighted above might relate to earlier attempts.

I've reverted to calling directly from Miele swagger and I get:

curl -X 'PUT' \
  'https://api.mcs3.miele.com/v1/devices/**REDACTED**/actions' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer **REDACTED**' \
  -H 'Content-Type: application/json' \
  -d '{
  "powerOn": 1
}'

Response code 204

curl -X 'PUT' \
  'https://api.mcs3.miele.com/v1/devices/**REDACTED**/programs' \
  -H 'accept: */*' \
  -H 'Authorization: Bearer **REDACTED**' \
  -H 'Content-Type: application/json' \
  -d '{
  "programId": 215
}'
{
  "code": 400,
  "message": "Not Supported"
}

200 and 215 are both on the list of valid program types

[
  {
    "programId": 200,
    "program": "",
    "parameters": {}
  },
  {
    "programId": 202,
    "program": "Auto 45 - 60°C",
    "parameters": {}
  },
  {
    "programId": 203,
    "program": "ComfortWash 45°C",
    "parameters": {}
  },
  {
    "programId": 204,
    "program": "",
    "parameters": {}
  },
  {
    "programId": 205,
    "program": "Intensive 75°C",
    "parameters": {}
  },
  {
    "programId": 209,
    "program": "ComfortWash+  55°C",
    "parameters": {}
  },
  {
    "programId": 207,
    "program": "ExtraQuiet 50°C",
    "parameters": {}
  },
  {
    "programId": 210,
    "program": "Gentle 45°C",
    "parameters": {}
  },
  {
    "programId": 214,
    "program": "Maintenance programme ",
    "parameters": {}
  },
  {
    "programId": 215,
    "program": "Rinse salt ",
    "parameters": {}
  },
  {
    "programId": 0,
    "program": "",
    "parameters": {}
  },
  {
    "programId": 0,
    "program": "",
    "parameters": {}
  },
  {
    "programId": 0,
    "program": "",
    "parameters": {}
  },
  {
    "programId": 0,
    "program": "",
    "parameters": {}
  },
  {
    "programId": 0,
    "program": "",
    "parameters": {}
  }
]

Note from above log

      "state|remoteEnable|fullRemoteControl": true,
      "state|remoteEnable|smartGrid": false,
      "state|remoteEnable|mobileStart": true,
astrandb commented 2 days ago

Thank you for your efforts to debug and clarify the issue. The problem is with Miele 3rd parti API and not with this integration.

blacknell commented 2 days ago

Any suggestions for how to go back to Miele on this. Reading the history on this repo I sense it's very unpredictable.

astrandb commented 2 days ago

You could report the behaviour (or lack of...) to developer@miele.com I always get polite answers but it is obvious that they prioritize the internal API that they use for their own apps. You could mention that there are some 11000 users nowadays of this integration in Home Assistant so they might consider to look at the problem.