Created
December 9, 2025 23:38
-
-
Save tibers/42b3ebcaa825800c32b8755505ba6c39 to your computer and use it in GitHub Desktop.
python to check daikin or skyporthome API for auxilery heat being used in a heat pump
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Daikin One API - Check Auxiliary Heater Status | |
| This script authenticates with the Daikin Skyport API (user API, not integrator), | |
| retrieves the list of devices, and checks the AuxHeaterStatus for a specified device. | |
| This was written with a lot of Claude. | |
| This script assumes you only have one thermostat and uses the first device UUID returned. | |
| If you have a different device as your first device, it will not pick the correct one. | |
| This is unlikely. | |
| The script will output: | |
| Authenticating... | |
| Authentication successful! | |
| Retrieving devices... | |
| Available devices: | |
| - Main Room (ONEPLUS) at Unknown | |
| ID: <redacted> | |
| Checking auxiliary heater status for device: <redacted> | |
| ================================================== | |
| Auxiliary Heater Status: False | |
| ================================================== | |
| Additional Information: | |
| Mode: 0 | |
| Equipment Status: 5 | |
| Indoor Temp: 19.8°C | |
| Outdoor Temp: None°C | |
| Heat Setpoint: 20°C | |
| Aux heater status is True for running on aux heat, or False for not using aux heat. | |
| This value is True in emergency heat mode. | |
| Other documentation: | |
| https://github.com/apetrycki/daikinskyport/blob/master/API_info.md | |
| https://github.com/TJCoffey/DaikinSkyportToMQTT | |
| Troubleshooting: | |
| If the thermostat is connected to wifi and Daikin Cloud, but this script is returning | |
| that the thermostat is offline, it's because you have exceeded the rate limit. | |
| The rate limit is really, really low. Consider only running this every 15 or 30 minutes. | |
| The rate limit seems to refresh hourly. | |
| """ | |
| import requests | |
| import sys | |
| from typing import Optional, Dict, Any | |
| # API Configuration | |
| BASE_URL = "https://api.daikinskyport.com" | |
| EMAIL = "YOUR_EMAIL_HERE" # Replace with your account email | |
| PASSWORD = "YOUR_PASSWORD_HERE" # Replace with your account password | |
| def get_access_token(email: str, password: str) -> Optional[str]: | |
| """ | |
| Authenticate and retrieve an access token. | |
| Args: | |
| email: User email address | |
| password: User password | |
| Returns: | |
| Access token string or None if authentication fails | |
| """ | |
| url = f"{BASE_URL}/users/auth/login" | |
| headers = { | |
| "Accept": "application/json", | |
| "Content-Type": "application/json" | |
| } | |
| payload = { | |
| "email": email, | |
| "password": password | |
| } | |
| try: | |
| response = requests.post(url, json=payload, headers=headers) | |
| response.raise_for_status() | |
| data = response.json() | |
| return data.get("accessToken") | |
| except requests.exceptions.RequestException as e: | |
| print(f"Error authenticating: {e}") | |
| return None | |
| def get_devices(access_token: str) -> Optional[list]: | |
| """ | |
| Retrieve the list of devices. We assume you only have one thermostat, so it uses the first one. | |
| Args: | |
| access_token: Bearer token for authentication | |
| Returns: | |
| List of devices or None if request fails | |
| """ | |
| url = f"{BASE_URL}/devices" | |
| headers = { | |
| "Accept": "application/json", | |
| "Authorization": f"Bearer {access_token}" | |
| } | |
| try: | |
| response = requests.get(url, headers=headers) | |
| response.raise_for_status() | |
| return response.json() | |
| except requests.exceptions.RequestException as e: | |
| print(f"Error retrieving devices: {e}") | |
| return None | |
| def get_device_data(device_id: str, access_token: str) -> Optional[Dict[str, Any]]: | |
| """ | |
| Retrieve thermostat data for a specific device. | |
| Args: | |
| device_id: UUID of the device | |
| access_token: Bearer token for authentication | |
| Returns: | |
| Device data dictionary or None if request fails | |
| """ | |
| url = f"{BASE_URL}/deviceData/{device_id}" | |
| headers = { | |
| "Accept": "application/json", | |
| "Authorization": f"Bearer {access_token}" | |
| } | |
| try: | |
| response = requests.get(url, headers=headers) | |
| response.raise_for_status() | |
| return response.json() | |
| except requests.exceptions.RequestException as e: | |
| print(f"Error retrieving device data: {e}") | |
| if hasattr(e, 'response') and e.response is not None: | |
| try: | |
| error_data = e.response.json() | |
| print(f"Error details: {error_data}") | |
| # If device is offline, explain this to user | |
| if error_data.get("message") == "DeviceOfflineException": | |
| print("\n⚠️ Your thermostat appears to be offline or disconnected from the cloud.") | |
| print("Please check:") | |
| print(" - Is the thermostat powered on?") | |
| print(" - Is it connected to WiFi?") | |
| print(" - Can you control it from the Daikin One Home app?") | |
| return {"offline": True} | |
| except: | |
| if e.response.text: | |
| print(f"Response content: {e.response.text}") | |
| return None | |
| def main(): | |
| """Main function to check auxiliary heater status.""" | |
| # Step 1: Authenticate and get access token | |
| print("Authenticating...") | |
| access_token = get_access_token(EMAIL, PASSWORD) | |
| if not access_token: | |
| print("Failed to authenticate. Please check your credentials.") | |
| sys.exit(1) | |
| print("Authentication successful!") | |
| # Step 2: Get list of devices | |
| print("\nRetrieving devices...") | |
| devices_data = get_devices(access_token) | |
| if not devices_data: | |
| print("Failed to retrieve devices.") | |
| sys.exit(1) | |
| # Display available devices | |
| print("\nAvailable devices:") | |
| all_devices = [] | |
| for device in devices_data: | |
| device_id = device.get("id") | |
| device_name = device.get("name", "Unknown") | |
| device_model = device.get("model", "Unknown") | |
| location_name = device.get("locationName", "Unknown") | |
| print(f" - {device_name} ({device_model}) at {location_name}") | |
| print(f" ID: {device_id}") | |
| all_devices.append(device_id) | |
| if not all_devices: | |
| print("No devices found.") | |
| sys.exit(1) | |
| # Step 3: Get device data for the first device (or specify which one) | |
| device_id = all_devices[0] # Using first device | |
| print(f"\nChecking auxiliary heater status for device: {device_id}") | |
| device_data = get_device_data(device_id, access_token) | |
| if not device_data: | |
| print("Failed to retrieve device information.") | |
| sys.exit(1) | |
| if device_data.get("offline"): | |
| print("\nCannot retrieve auxHeaterStatus - device is offline.") | |
| sys.exit(1) | |
| # Step 4: Check auxHeaterStatus | |
| aux_heater_status = device_data.get("auxHeaterStatus") | |
| if aux_heater_status is not None: | |
| print(f"\n{'='*50}") | |
| print(f"Auxiliary Heater Status: {aux_heater_status}") | |
| print(f"{'='*50}") | |
| # Display additional relevant information | |
| print(f"\nAdditional Information:") | |
| print(f" Mode: {device_data.get('mode')}") | |
| print(f" Equipment Status: {device_data.get('equipmentStatus')}") | |
| print(f" Indoor Temp: {device_data.get('tempIndoor')}°C") | |
| print(f" Outdoor Temp: {device_data.get('outsideTemp')}°C") | |
| print(f" Heat Setpoint: {device_data.get('hspHome')}°C") | |
| else: | |
| print("\nauxHeaterStatus not found in device information.") | |
| print("Available fields:", list(device_data.keys())) | |
| return aux_heater_status | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment