MieleRESTServer -- Miele@home Without Cloud Possible

Wauw, thanks for the quick reply.
That helped but now I’m stuck in the keys phase.

When generating the device keys I get the error that it is missing the module numpy. However when I try to install numpy it says it’s already there.

~/Downloads/MieleRESTServer-master$ virtualenv venv
source venv/bin/activate
pip install -r requirements.txt
./generate-keys.py > ./keys.json
created virtual environment CPython3.12.3.final.0-64 in 63ms
  creator CPython3Posix(dest=/home/alexander/Downloads/MieleRESTServer-master/venv, clear=False, no_vcs_ignore=False, global=False)
  seeder FromAppData(download=False, pip=bundle, via=copy, app_data_dir=/home/alexander/.local/share/virtualenv)
    added seed packages: Flask_RESTful==0.3.10, aniso8601==10.0.1, blinker==1.9.0, certifi==2026.1.4, cffi==2.0.0, charset_normalizer==3.4.4, click==8.3.1, cryptography==46.0.3, flask==3.1.2, idna==3.11, itsdangerous==2.2.0, jinja2==3.1.6, markupsafe==3.0.3, numpy==2.4.1, pip==24.0, pycparser==2.23, pytz==2025.2, pyyaml==6.0.3, requests==2.32.5, six==1.17.0, urllib3==2.6.3, werkzeug==3.1.5
  activators BashActivator,CShellActivator,FishActivator,NushellActivator,PowerShellActivator,PythonActivator
Requirement already satisfied: cryptography in ./venv/lib/python3.12/site-packages (from -r requirements.txt (line 1)) (46.0.3)
Requirement already satisfied: Flask in ./venv/lib/python3.12/site-packages (from -r requirements.txt (line 2)) (3.1.2)
Requirement already satisfied: flask_restful in ./venv/lib/python3.12/site-packages (from -r requirements.txt (line 3)) (0.3.10)
Requirement already satisfied: numpy in ./venv/lib/python3.12/site-packages (from -r requirements.txt (line 4)) (2.4.1)
Requirement already satisfied: PyYAML in ./venv/lib/python3.12/site-packages (from -r requirements.txt (line 5)) (6.0.3)
Requirement already satisfied: Requests in ./venv/lib/python3.12/site-packages (from -r requirements.txt (line 6)) (2.32.5)
Requirement already satisfied: cffi>=2.0.0 in ./venv/lib/python3.12/site-packages (from cryptography->-r requirements.txt (line 1)) (2.0.0)
Requirement already satisfied: blinker>=1.9.0 in ./venv/lib/python3.12/site-packages (from Flask->-r requirements.txt (line 2)) (1.9.0)
Requirement already satisfied: click>=8.1.3 in ./venv/lib/python3.12/site-packages (from Flask->-r requirements.txt (line 2)) (8.3.1)
Requirement already satisfied: itsdangerous>=2.2.0 in ./venv/lib/python3.12/site-packages (from Flask->-r requirements.txt (line 2)) (2.2.0)
Requirement already satisfied: jinja2>=3.1.2 in ./venv/lib/python3.12/site-packages (from Flask->-r requirements.txt (line 2)) (3.1.6)
Requirement already satisfied: markupsafe>=2.1.1 in ./venv/lib/python3.12/site-packages (from Flask->-r requirements.txt (line 2)) (3.0.3)
Requirement already satisfied: werkzeug>=3.1.0 in ./venv/lib/python3.12/site-packages (from Flask->-r requirements.txt (line 2)) (3.1.5)
Requirement already satisfied: aniso8601>=0.82 in ./venv/lib/python3.12/site-packages (from flask_restful->-r requirements.txt (line 3)) (10.0.1)
Requirement already satisfied: six>=1.3.0 in ./venv/lib/python3.12/site-packages (from flask_restful->-r requirements.txt (line 3)) (1.17.0)
Requirement already satisfied: pytz in ./venv/lib/python3.12/site-packages (from flask_restful->-r requirements.txt (line 3)) (2025.2)
Requirement already satisfied: charset_normalizer<4,>=2 in ./venv/lib/python3.12/site-packages (from Requests->-r requirements.txt (line 6)) (3.4.4)
Requirement already satisfied: idna<4,>=2.5 in ./venv/lib/python3.12/site-packages (from Requests->-r requirements.txt (line 6)) (3.11)
Requirement already satisfied: urllib3<3,>=1.21.1 in ./venv/lib/python3.12/site-packages (from Requests->-r requirements.txt (line 6)) (2.6.3)
Requirement already satisfied: certifi>=2017.4.17 in ./venv/lib/python3.12/site-packages (from Requests->-r requirements.txt (line 6)) (2026.1.4)
Requirement already satisfied: pycparser in ./venv/lib/python3.12/site-packages (from cffi>=2.0.0->cryptography->-r requirements.txt (line 1)) (2.23)
Traceback (most recent call last):
  File "/home/alexander/Downloads/MieleRESTServer-master/./generate-keys.py", line 21, in <module>
    import MieleCrypto
  File "/home/alexander/Downloads/MieleRESTServer-master/MieleCrypto.py", line 22, in <module>
    import numpy as np
ModuleNotFoundError: No module named 'numpy'

Never mind, got it working with some ChatGPT help.
The trick was to run it like this:

python generate-keys.py > keys.json

So I got the server running but something is nog right. If I try http://127.0.0.1:5001/generat-summary/, I get a 404

alexander@Ubuntu-docker:~$ systemctl status MieleRESTServer.service
● MieleRESTServer.service - Miele REST Interface Server
     Loaded: loaded (/etc/systemd/system/MieleRESTServer.service; enabled; preset: enabled)
     Active: active (running) since Mon 2026-01-12 17:15:10 CET; 13min ago
   Main PID: 5208 (python3)
      Tasks: 2 (limit: 4596)
     Memory: 38.8M (peak: 68.5M swap: 3.3M swap peak: 3.3M)
        CPU: 784ms
     CGroup: /system.slice/MieleRESTServer.service
             └─5208 /usr/local/lib/MieleRESTServer/venv_MieleRESTServer/bin/python3 /usr/local/lib/MieleRESTServer/Server.py -b 127.0.0.1 -p 5001

Jan 12 17:15:11 Ubuntu-docker python3[5208]: WebUI disabled.
Jan 12 17:15:11 Ubuntu-docker python3[5208]:  * Serving Flask app 'Server'
Jan 12 17:15:11 Ubuntu-docker python3[5208]:  * Debug mode: off
Jan 12 17:15:11 Ubuntu-docker python3[5208]: WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
Jan 12 17:15:11 Ubuntu-docker python3[5208]:  * Running on http://127.0.0.1:5001
Jan 12 17:15:11 Ubuntu-docker python3[5208]: Press CTRL+C to quit
Jan 12 17:16:56 Ubuntu-docker python3[5208]: 127.0.0.1 - - [12/Jan/2026 17:16:56] "GET /generate-summary/ HTTP/1.1" 404 -
Jan 12 17:16:56 Ubuntu-docker python3[5208]: 127.0.0.1 - - [12/Jan/2026 17:16:56] "GET /favicon.ico HTTP/1.1" 404 -
Jan 12 17:19:43 Ubuntu-docker python3[5208]: 127.0.0.1 - - [12/Jan/2026 17:19:43] "GET /generate-summary/ HTTP/1.1" 404 -
Jan 12 17:19:43 Ubuntu-docker python3[5208]: 127.0.0.1 - - [12/Jan/2026 17:19:43] "GET /favicon.ico HTTP/1.1" 404 -

Any pointers on what I’ve done wrong?

Just to be complete, I’ve got this running on Ubuntu 24.04, on a Proxmox VM.

Edit: never mind, I started from scratch and now it works. I suspect I f’ed things up with copying the key to the washing machine.

Glad you got it working. What’s your model and did you get all 3 features working (the summary, remote start & DOP2) so I can update the compatibilit list?

Are you using it with Home Assistant?

1 Like

It’s a washing machine WSD663 WCS (already in your list), the summary and remote start are working. DOP2 is not but that’s in line with your table.

I’m planning on using it in Home Assistant.

I’ve the sensor now in HA. That part was a lot easier than the rest :sweat_smile:

Just out of curriosity, do you think it will be possible at some point to set the programms using this server? Or is that not possible at all? (this REST stuff is quite new to me)

Hi Alex,

it is already possible on those devices that accept DOP2 commands (see post #107 in this chain). Unfortunately yours does not. I suspect this to be an issue with the configuration or the firmware, rather than the device itself, so I suspect that this will be resolved eventually.

There is also the remaining task of exposing the functionality through some higher-level API, rather than by using the server to send handcrafted raw commands to the device. Right now, it takes 3 commands to program a device – this should be one high-level command to the server, which then figures out what low-level commands to issue to the device. Pull requests welcome :slight_smile:

Don’t expect any pull requests from me on short term. I somewhat understand what you’re trying to say in the second alinea but I would not know where to start trying to figure this out technically.

I’ve run into an issue.
For context, this is my workflow: I fill up my washinmachine (WSD663), choose a programm and set the timer to the amount of hours I want, generally 12 hours.
I’ve integrated the REST server in home assistant, home assistant will notice the washingmachine is ready to start and will find the cheapest energy hour within the time I’ve set on the washingmachine timer. At that time it will send the start command to the washing machine.

Now the issue that I’ve noticed is that the washingmachine seems to go in some sort of deep sleep after a couple of hours. So, if my start time is before the machine goes into deep sleep, there is no issue and the machine just starts. But after that it does not react.
I thought I would fix that by using the wakeup command before the start command but that does not seem to do the trick.

“http://<server_ip>:5001/wakeup/wasmachine” In the browser gives me this

[{"Success": {"DeviceAction": 0}}]

but if I run the same url in Bruno as Post command I get:

{ "message": "The method is not allowed for the requested URL." }

Any ideas or pointers where to look at are more than welcome.

Alex,

that’s a pretty neat way of using it!

the /wakeup endpoint certainly should be a POST endpoint because it actually changes the device state. Currently, it’s not, as the correct functioning of that endpoint was only understood later. So I’d recommend simply changing your Bruno code to use GET. Or you can just use wget to call the wakup endpoint. Let me know if that works.

Ultimately this will be resolved with the Rust rewrite (MieleRESTServer/dop2rs at master · akappner/MieleRESTServer · GitHub), which will feature a new API that also integrates with existing HA Miele integrations.

Thanks, pretty pleased with it myself :smiling_face:

Last night I ran a litlle tracker on the generate-summary to see what changes. So everytime something changes in the generate-summary json it logs the change in a file. It checked it with a 5 sec. interval. Here is a small recap of the log file:

2026-02-04T18:41:26 | DecodedProgramID: Automatic -> DrainSpin ; ProgramID: 1 -> 21 ; RemainingMinutes: 159 -> 12 ; RemainingTime: [2, 39] -> [0, 12] ; RemoteEnable: [15, 0, 0] -> [7, 0, 0] ; StandbyState: 2 -> 1 ; StartTime: [6, 41] -> [24, 0] ; TargetTemperature: [4000, -32768, -32768] -> [-32766, -32768, -32768]
2026-02-04T18:41:56 | RemoteEnable: [7, 0, 0] -> [15, 0, 0]
2026-02-04T18:42:27 | StartTime: [24, 0] -> [23, 59]
...only logs of StartTime changing
2026-02-04T18:54:31 | StartTime: [23, 48] -> [23, 47]
2026-02-04T18:55:31 | StandbyState: 1 -> 3 ; StartTime: [23, 47] -> [23, 46]
2026-02-04T18:56:32 | StandbyState: 3 -> 2 ; StartTime: [23, 46] -> [23, 45]
2026-02-04T18:57:32 | StartTime: [23, 45] -> [23, 44]
...only logs of StartTime changing
2026-02-05T07:25:43 | StartTime: [11, 17] -> [11, 16]
2026-02-05T07:26:43 | StartTime: [11, 16] -> [11, 15]
2026-02-05T07:27:44 | StartTime: [11, 15] -> [11, 14]

So after about 15 minutes the StandbyState is changing but I know for sure that the machine can still be started with the POST start command. After that moment nothing changes in the logs except for the StartTime. The fact that the StartTime is changing implies (to me) that the machine is still awake. However, at 02:00 it was supposed to start and it didn’t.
This morning I tried the wakeup with GET and wget, but no reaction. Also no reaction on the POST start command.
I’m out of ideas as is ChatGPT :sweat_smile:

Will this also work for my machine (WSD663) as this does not support DOP2?

I really appreciate this tool and your time. Although it’s not working for me the way I would like at the moment. It’s been an interesting learning curve so far.

Thanks for the detailed reports. Was the timer still running in the morning? If not – the device reached 0 on the timer and still didn’t start? What if you include the call to /wakeup in your polling script – does the device still go into “StandbyState → 3”?

0x03 in “StandbyState” just means “suspending”, and 0x02 is “in suspend”, with 0x01 being “active”. So generally this isn’t abnormal device behavior.

There might also be a race condition between the “wakeup” call and the start command. The official app basically spams the wakeup call before continuing with the actual command. I avoided that, but then agian, I never tried sending a start command back-to-back with a wakeup call. So let’s try doing the same thing… can we send 1000 wakeup calls and THEN proceed with start?

I’d suggest trying both: 1) keeping the device awake by periodically issuing the wakeup; and 2) issuing 1000 wakeups before issuing the start. Of course, that’s ugly – we’ll figure out how to do better once we know that resolves the issue.

As for the Rust rewrite, the problem with not supporting DOP2 will not be resolved by rewriting the server – the rewrite is mainly intended to go from the very hackish experimental API to something that’s stable and has proper error handling. To enable DOP2 on unsupported devices may ultimately require a firmware mod.

1 Like

Yes

Tried it, unfortunately no response nor a change in the log file

I will set up a new experiment with the /wakeup included. Once I’ve some findings I’ll let you know.

Unfortunately this does not work either. After +/- 15 minutes it goed in StandbyState 3 and a minute later in 2. Despite the wakeup calls every minute.

I’ve to correct myself here. The moment the StandbyState is changing the machine does no longer react to the start command.

The only way I get it out of this sleepmode is by physically turning the programm knob or just wait for the timer to run out of time.

I’m thinking about going back to the official app just to see if I can reproduce this behaviour.

Hi,

your device might need a separate “switch on” call before it is issued the start command if it goes into deep sleep. I have added the corresponding logic to the “extended-wakeup-2” branch, please try if that works. We have seen this before in DOP2 devices that require a three-step sequence to wake up from deep sleep; maybe your device, despite being non-DOP2, needs the same. Please check out that test branch (git fetch && git switch extended-wakeup-2) and let me know if it works.

If this still doesn’t work, we can fiddle with other commands to make your device come back from deep sleep.

Hi there , I have the following I would like to help test but you’ll have to give me steps to follow like im 5 yrs old and very first time building REST server because it will be
CM6360 Coffee Machine
G7169 Dishwasher
H7264BP Oven
KFNS 7784 D Fridge Freezer
I hope I can help

Hi,

please refer to the README (MieleRESTServer/README.md at master · akappner/MieleRESTServer · GitHub); let me know if you run into any specific issues.

BR

That hardcoded key doesn’t seem to work. And I’ve tried using the Miele app in the meantime and that also seems to fail on the “sending key to device” stage. So I don’t know if I’ve just got a dodgy device, is there anything else we can try?

I know it sucks for you but I’m actually super glad to hear that the official app doesn’t work either – that means I can stop looking for the bug in my code :wink:

There’s a few more things we can try though. It appears that there is a hidden service menu that offers additional Miele@Home configuration options on some Miele devices. How to get into this menu is described at (https://www.youtube.com/watch?v=HWC69nLUmGI ) – you can see the menu at position 9:47. Are you able to access this menu on your device? If so, what options can you change?