-
Notifications
You must be signed in to change notification settings - Fork 116
Inability to reliably deactivate 'comfort' program (clear manual override) on CU401B Heat Pump #715
Description
When a heating circuit is in a manual override state (activated via the comfort program), it is not possible to reliably return it to its time-based schedule by deactivating the comfort program.
Calling circuit.deactivateProgram("comfort") or the equivalent raw API call device.service.setProperty(..., "deactivate", {}) often completes without an error, but the comfort: { active: True } property remains unchanged. This leaves the circuit stuck in a manual state, and the only way to clear it is through the official Viessmann mobile app.
This issue has been observed on a Viessmann Heat Pump with a CU401B controller and affects both of its heating circuits (ID '0' and '1').
Environment
- PyViCare Version: 2.58.0
- Device: Viessmann Heat Pump with CU401B controller
- Heating Circuits:
- Circuit 0: Radiators
- Circuit 1: UFH (Underfloor Heating)
Steps to Reproduce
The following sequence reliably demonstrates the issue:
- Set Manual Mode: Activate the comfort program on a circuit (e.g., circuit '0').
# (After connecting to the device)
circuit_0 = device.circuits[0]
circuit_0.setMode("dhwAndHeatingCooling") # Ensure heating is on
circuit_0.setComfortTemperature(26)
time.sleep(2)
circuit_0.activateProgram("comfort")
-
Wait and Verify: After waiting ~10-20 seconds, check the status. The API correctly reports that the comfort program is active.
- heating.circuits.0.operating.modes.active -> dhwAndHeatingCooling
- heating.circuits.0.operating.programs.comfort -> properties: { active: { value: True } }
-
Attempt to Revert to Schedule: Call the deactivate command.
1 circuit_0.deactivateProgram("comfort")
- Wait and Verify Result: After waiting again (even several minutes), check the status.
Expected Behavior
After step 3, the heating.circuits.0.operating.programs.comfort feature's active property should change to False. The circuit should now follow its default time-based schedule (e.g., the normal program).
Actual Behavior
The deactivateProgram("comfort") command completes without any API error. However, the active property of the comfort program remains True. The circuit is stuck in manual override mode and does not return to its schedule.
Workarounds Attempted (and their results)
- Aggressive Mode Cycling: We discovered that cycling the operating modes (standby -> dhw -> dhwAndHeatingCooling) can sometimes force the Comfort Active flag to False, but this has proven to be inconsistent and not reliable.
- Activating another program: Attempting to activate("normal") results in a COMMAND_NOT_FOUND error, indicating it's not a valid standalone program to activate.
Minimal Reproducible Code Example
1 import sys
2 import time
3 from PyViCare.PyViCare import PyViCare
4
5 # Credentials
6 CLIENT_ID = "YOUR_CLIENT_ID" # Replace with your client ID
7 EMAIL = "YOUR_EMAIL" # Replace with your email
8 PASSWORD = "YOUR_PASSWORD" # Replace with your password
9 CIRCUIT_ID_TO_TEST = "0" # Change to "1" for the other circuit
10
11 def get_comfort_status(device, circuit_id):
12 try:
13 prop = f"heating.circuits.{circuit_id}.operating.programs.comfort"
14 data = device.service.getProperty(prop)
15 return data['properties']['active']['value']
16 except Exception as e:
17 print(f"Error reading status: {e}")
18 return None
19
20 def main():
21 vicare = PyViCare()
22 vicare.initWithCredentials(EMAIL, PASSWORD, CLIENT_ID)
23
24 device = vicare.devices[0].asHeatPump()
25 circuit = None
26 for c in device.circuits:
27 if str(c.id) == CIRCUIT_ID_TO_TEST:
28 circuit = c
29 break
30
31 if not circuit:
32 print(f"Circuit {CIRCUIT_ID_TO_TEST} not found.")
33 return
34
35 print(f"--- Testing on Circuit {circuit.id} ({circuit.getName()}) ---")
36
37 # 1. Activate Manual Comfort
38 print("\nStep 1: Activating Manual Comfort at 26°C...")
39 circuit.setMode("dhwAndHeatingCooling")
40 circuit.setComfortTemperature(26)
41 time.sleep(2)
42 circuit.activateProgram("comfort")
43 print("Command sent. Waiting 15s...")
44 time.sleep(15)
45
46 status_after_on = get_comfort_status(device, circuit.id)
47 print(f"Status after ON: Comfort Active = {status_after_on}")
48 if not status_after_on:
49 print("-> FAILED: Could not even activate comfort mode.")
50 return
51
52 # 2. Deactivate Comfort to return to schedule
53 print("\nStep 2: Deactivating Comfort to return to schedule...")
54 circuit.deactivateProgram("comfort")
55 print("Command sent. Waiting 15s...")
56 time.sleep(15)
57
58 # 3. Check final status
59 final_status = get_comfort_status(device, circuit.id)
60 print(f"\n--- FINAL STATUS ---")
61 print(f"Expected: Comfort Active = False")
62 print(f"Actual: Comfort Active = {final_status}")
63
64 if final_status == False:
65 print("\nSUCCESS: Override was cleared!")
66 else:
67 print("\nFAILURE: Override was NOT cleared.")
68
69 if __name__ == "__main__":
70 main()