MieleRESTServer -- Miele@home Without Cloud Possible

If the server isn’t giving you any response, the problem is with the server or its setup, not with the oven. If the server were working correctly but the oven were not, the server would respond with some type of error message.

Can you show me the content of your /etc/MieleRESTServer.config? What command are you using to start the server?

You also mentioned you’re on Windows. My instructions are written for Linux-based OS – I’m sure there’s a way to run this on Windows as well, but I don’t know how. So if you figure it out, I’d appreciate if you could send me a paragraph for the README on how to get it running on Windows.

Regarding the different pairing methods… yes, the oven can also scan for wi-fi networks by itself. I can’t really think of a scenario where this would be useful, so I never implemented any support for it.

Whohoo, success!! I managed to do the commissioning with my phone using a REST app.

Here is what my oven says:
C:\Users\albre>curl http://127.0.0.1:5001/generate-summary
{“SpeedOven”: {“Status”: 12, “InternalState”: 0, “ProgramType”: 1, “ProgramID”: 16034, “ProgramPhase”: 0, “RemainingTime”: [0, 0], “StartTime”: [0, 0], “TargetTemperature”: [-32768, -32768, -32768], “Temperature”: [-32768, -32768, -32768], “SignalInfo”: false, “SignalFailure”: false, “SignalDoor”: false, “RemoteEnable”: [15, 0, 0], “ProcessAction”: 0, “DeviceAction”: 0, “Light”: 2, “StandbyState”: 1, “ElapsedTime”: [0, 0], “DeviceType”: 13, “SubType”: 0, “DeviceName”: “”, “AppSupport”: 661, “FctSupport”: 3, “XKMSupport”: 7, “ProtocolVersion”: 4, “DeviceIdentLabel”: {“Version”: “E”, “FabNumber”: “000139008181”, “FabIndex”: “00”, “TechType”: “H7240BM”, “MatNumber”: “11804520”, “SWIDs”: [5464, 20487, 25228, 5479, 25301, 25307, 25247, 20571, 25239, 5651, 20366, 20462]}, “XKMIdentLabel”: {“Version”: “E”, “FabNumber”: “000000848340”, “FabIndex”: “00”, “TechType”: “EK057”, “MatNumber”: “11913741”, “SWIDs”: [6534], “ReleaseVersion”: “08.32”}, “DecodedProgramPhase”: “NotUsed”, “DecodedStatus”: “Service”, “DecodedDeviceType”: “OvenWithMicrowave”, “RemainingMinutes”: 0, “ElapsedMinutes”: 0, “Progress”: “0.0”}}

Now I just have to figure out how to control it…

OK, so what do I do next? On the Miele API they had the following:

How can I get to these endpoints through the server now?

Now for the other oven (H7263BP). I am getting response 403 for the /Security/Commision. Bummer!

Congratz on getting it to work!

403 is the expected response if the device has already been provisioned-- you mentioned using the official app before, so you’ll need to clear the existing configuration. Typically by long-holding a button when in the configuration menu – check your specific manual.

For remote programming/start, you’ll need to say what your device supports.

curl http://127.0.0.1:5001/start/SpeedOven

See what this gives you. If it says “Supported” and “Ready”, send a POST request to that same endpoint and it should start. If not, it needs to be programmed first.

For programming, try

curl http://127.0.0.1:5001/wakeup/SpeedOven

curl http://127.0.0.1:5001/walkdop2tree/SpeedOven

And see what this gives you.

Success!!! I got the second oven commissioned too. (I had to go through the oven menu and reset the wifi settings.)

For your tables, The H7240BM oven responds as follows:

curl.exe -X GET (IP):5001/generate-summary/H7240BM
{“Status”: 1, “InternalState”: 0, “ProgramType”: 1, “ProgramID”: 0, “ProgramPhase”: 0, “RemainingTime”: [0, 0], “StartTime”: [0, 0], “TargetTemperature”: [-32768, -32768, -32768], “Temperature”: [-32768, -32768, -32768], “SignalInfo”: false, “SignalFailure”: false, “SignalDoor”: false, “RemoteEnable”: [15, 0, 0], “ProcessAction”: 0, “DeviceAction”: 0, “Light”: 2, “StandbyState”: 2, “ElapsedTime”: [0, 0], “DeviceType”: 13, “SubType”: 0, “DeviceName”: “”, “AppSupport”: 661, “FctSupport”: 3, “XKMSupport”: 7, “ProtocolVersion”: 4, “DeviceIdentLabel”: {“Version”: “E”, “FabNumber”: “000139008181”, “FabIndex”: “00”, “TechType”: “H7240BM”, “MatNumber”: “11804520”, “SWIDs”: [5464, 20487, 25228, 5479, 25301, 25307, 25247, 20571, 25239, 5651, 20366, 20462]}, “XKMIdentLabel”: {“Version”: “E”, “FabNumber”: “000000848340”, “FabIndex”: “00”, “TechType”: “EK057”, “MatNumber”: “11913741”, “SWIDs”: [6534], “ReleaseVersion”: “08.32”}, “DecodedProgramPhase”: “NotUsed”, “DecodedProgramID”: “NotSelected”, “DecodedStatus”: “Off”, “DecodedDeviceType”: “OvenWithMicrowave”, “RemainingMinutes”: 0, “ElapsedMinutes”: 0, “Progress”: “0.0”}

curl.exe -X GET (IP):5001/start/H7240BM
{“DeviceReadyToStart”: false, “DeviceRemoteStartCapable”: true}

curl.exe -X GET (IP):5001/walkdop2tree/H7240BM
{“error”: “DOP2 Root Node not found”, “device”: “192.168.10.113”}

curl.exe -X GET (IP):5001/wakeup/H7240BM
[{“Success”: {“DeviceAction”: 0}}]

The H7263BP responds as follows:

curl.exe -X GET (IP):5001/generate-summary/H7263BP
{“Status”: 1, “InternalState”: 0, “ProgramType”: 1, “ProgramID”: 0, “ProgramPhase”: 0, “RemainingTime”: [0, 0], “StartTime”: [0, 0], “TargetTemperature”: [-32768, -32768, -32768], “Temperature”: [-32768, -32768, -32768], “SignalInfo”: false, “SignalFailure”: false, “SignalDoor”: false, “RemoteEnable”: [15, 0, 0], “ProcessAction”: 0, “DeviceAction”: 0, “Light”: 2, “StandbyState”: 3, “ElapsedTime”: [0, 0], “DeviceType”: 12, “SubType”: 0, “DeviceName”: “”, “AppSupport”: 661, “FctSupport”: 3, “XKMSupport”: 7, “ProtocolVersion”: 4, “DeviceIdentLabel”: {“Version”: “E”, “FabNumber”: “000138768063”, “FabIndex”: “00”, “TechType”: “H7263BP”, “MatNumber”: “11804780”, “SWIDs”: [5462, 20487, 25228, 5472, 25300, 25307, 25247, 20417, 25224, 5651, 20366, 20462]}, “XKMIdentLabel”: {“Version”: “E”, “FabNumber”: “000000520924”, “FabIndex”: “00”, “TechType”: “EK057”, “MatNumber”: “11913740”, “SWIDs”: [6534], “ReleaseVersion”: “08.32”}, “DecodedProgramPhase”: “NotUsed”, “DecodedProgramID”: “NotSelected”, “DecodedStatus”: “Off”, “DecodedDeviceType”: “Oven”, “RemainingMinutes”: 0, “ElapsedMinutes”: 0, “Progress”: “0.0”}

curl.exe -X GET (IP):5001/start/H7263BP
{“DeviceReadyToStart”: false, “DeviceRemoteStartCapable”: true}

curl.exe -X GET (IP):5001/walkdop2tree/H7263BP
{“error”: “DOP2 Root Node not found”, “device”: “192.168.10.115”}

curl.exe -X GET (IP):5001/wakeup/H7263BP
[{“Success”: {“DeviceAction”: 0}}]

Great. So to exercise the remote start, try to program a start timer on the device (e.g. “start in 6 hours”). It should then say “DeviceReadyToStart: true”. You can then use the remote start functionality to cut that timer short by POSTing to the /start endpoint.

Since your devices do not expose the DOP2 programming interface, there is no current way to program the device from the server. This functionality appears possible, but I haven’t been able to get it to work yet. Are you able to obtain a firmware update file for one of your devices?

My ovens don’t seem to have any feature to run programs based on a timer.

My plan is to set up a packet sniffer on my network and see if I can catch the Miele@home app and oven “in the act” (so to speak) exchanging keys. Since the ovens expose only a http port, I’m hoping this is in plain text. Then I can snoop on the communications with the cloud based API and see what endpoints the Miele cloud is using.

is there a HACS integration planned? I am running HA on Home assistant yellow and Home Assistant OS.

OK, I’ve done a bit of snooping. I set up a wifi access point to see what the Miele app does during initial commissioning. This is the traffic between the app and my oven after it switches back to the wifi network:

The keys sent to /Security/Commissioning/ appear to be just dummies.
After the /Security/Cloud/TAN POST, the communiciation switches to TCP and TLSv1.2 between the oven and the cloud server. So, my plan to intercept the key has been foiled, so far. (Miele is smarter than that.) I also can’t see the endpoints being used. My next plan is to insert myself into the TLS which will work only if the oven accepts a security certificate from me…

2 Likes

This is great.

Can you try to trigger a firmware update on the oven, and see if you can capture the binary? Either through the app or on-air? Also, any chance you could post the full dump?

@ThUnD3r-Gr33n
I haven’t. I’m not familiar with HACS. But it’s open source if anybody wants to try.

HACS is just a distribution channel for custom HA integrations.

Sorry for the delay, I have been traveling. Here is the pcap file captured during initial connection from the app to the oven.

I don’t see any way to force a firmware update on the oven.

Hi,
Thanks @akappner for the awesome work!

I wanted to report that I have “WWD380 WCS” washer connected to the REST server running in docker and reporting to Home Assistant.

However I have a “TWD640WP” dryer and connecting to the wifi works but the provision-keys.sh fails with 403, I see that its expected if it has already been provisioned but this was straight out of the packaging and also after a factory reset, any ideas?

Hi,

that’s quite helpful. The app hits an endpoint /Update on the device (which I have not yet explored through the server), (presumably) receives some kind of version info, and then connects to xkmdwld2.miele.com via TLS. This seems to be the way to introduce firmware updates to the device. Unfortunately the app I have doesn’t even use/reference this endpoint, and it’s password protected. What version of the app do you have? Can you send me a link to the APK you downloaded?

@bencope
Thanks for the report on the 380. Regarding the 640, that’s very strange. Could you run nmap against your 640 and post it here, and also please attempt to use the following to configure the server:

{“GroupKey”:“11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111”,“GroupID”:“1111111111111111”}

I’m using version 4.15.2 of the Miele app from the play store.

Hi, @akappner,
This may be a bit off topic, but I have been exploring the cloud API used by the phone app. I managed to authenticate on the API and have found a few active DOP2 endpoints for my oven (H7263BP). The phone app talks to the cloud using DOP2. I’m attaching a file with the ones I have discovered. I’m not sure if there is any way to figure out what the payloads are. Do you have any clues?

By the way, I just noticed that Miele has a new developer portal. They introduced a new server and authentication method that is supposed to include device specific permissions. However, I have not been able to log on to the new server (https://auth.domestic.miele-iot.com/partner/realms/mcs/protocol/openid-connect/auth). It seems like it is still a work in progress.

Hi,

the file you posted is plaintext DOP2 packets, but without responses. My file “MieleDop2Structures.py” contains decoding logic for (most of) the structures you posted. This is great news actually, it confirms that your device does support the DOP2 protocol, but for some reason (Miele really wanting you to use their app, perhaps) only listens to that through the cloud. The caveat is that my efforts were directed at a washer, whereas your communication is from an oven, so a lot of the data structures are different.

I implemented a quick and dirty command line decoder to decode what you posted. If you pull the latest version of the repo, and run

python MieleDop2.py (node) (leaf) (hexbytes)

The node and leaf are the parameters in the URL.

You will get a – very rough, likely very incomplete – decoding of your files.

For example:

python MieleDop2.py 2 105 003c0002006903f303f1000b00010703f300020205000304000004060000000506000000060600010007060000000805000000090201000a0100000b0100

This is the SF_VALUE command sent to the device. Parameter number 5 is being queried (the same command can be used as POST to set the parameter).

The 1 1585 command you posted requests the “device context”, which is a large struct that contains a lot of internal state. Unfortunately I do not know the layout of the device context of your device, although my code is able to decode the structure (data types and lengths) of the context.

The most interesting thing to observe through this type of MITM you have set up would be a firmware update. Once we can get a firmware dump, we’ll understand the rest of these structures.

What happens when you try to trigger a firmware update on the app – can you also observe the DOP2 requests that follow?

Thank you. It is quite mysterious to me how you manage to decode these. I’ll try my best to make sense of it…

Regarding the firmware update, the app will only do it if there is a new version available. Unfortunately, my firmware is currently up to date. I’m going to disable automatic firmware updates and hope.

I have not been able to capture the outgoing DOP2 PUTs or POSTs. They go through a different connection. If I try to MITM that, the app hangs. What I was showing is only the responses that I get on websocket that gets opened up during the exchanges. I should have clarified that. (Honestly, I’m quite new to trying to understand all of these things.)

Aren’t we all (new to this?).

DOP2 is a fairly typical TLV (tag/length/value) protocol, popular in embedded applications. There’s a packet header that tells you how long the total packet is, and then it’s just a sequence of data types, lengths and contents. Fuzzing this would be interesting too – it seems non-trivial to write a DOP2 parser that’s hardened against specially crafted inputs.

I don’t want to wait until they come out with a new firmware. I managed to decrypt packet 145 in your PCAP… the key is, as they say, [0x11]*32. The payload is:

b’{\n\t"NewerAvailable":false,\n\t"CurrentVersion":“08.32”,\n\t"AvailableVersion":“”,\n\t"Type":“EK057”,\n\t"ReleaseNotes":“”,\n\t"UpdateInProgress":false\n}\n ’

So it’s basically the app asking the device what version is currently running. I’ll try to come up with an device simulator that pretends to run version 08.00, so that the app offers to update the fake device to the current one. Let’s see if that works. Let me know if you make any other progress.

Are you able to run arbitrary commands against that cloud API GET endpoint?