1- import asyncio
21import logging
32import voluptuous as vol
4- import aiohttp
5- import json
6- import urllib .parse
73import ast
84
9- from homeassistant .components .persistent_notification import create
105from datetime import datetime
116from dateutil .tz import gettz
12- from homeassistant .config_entries import SOURCE_IMPORT , ConfigEntry
7+ from homeassistant .config_entries import ConfigEntry
138from homeassistant .const import ATTR_DEVICE_ID , CONF_EMAIL , CONF_PASSWORD
149from homeassistant .helpers import config_validation as cv
1510from homeassistant .core import HomeAssistant , ServiceCall
2520
2621
2722_LOGGER = logging .getLogger (__name__ )
23+ SERVICE_REGISTRY = "service_registry"
2824
2925
3026HON_SCHEMA = vol .Schema (
@@ -59,6 +55,11 @@ def get_parameters(call):
5955 parameters_str = str (parameters_str )
6056 return ast .literal_eval (parameters_str )
6157
58+
59+ def _minutes_until (target : datetime , now : datetime ) -> int :
60+ """Return the number of whole minutes until the target time."""
61+ return max (0 , int ((target - now ).total_seconds () / 60 ))
62+
6263#def get_device_ids(hass, call):
6364# device_ids = call.data.get("device_id", [])
6465 #entity_ids = call.data.get("entity_id", [])
@@ -80,8 +81,6 @@ def get_device_ids(hass, call):
8081 return list (device_ids )
8182
8283
83- from homeassistant .helpers import entity_registry as er
84-
8584async def async_get_device_ids (hass , call ):
8685 device_ids = set (call .data .get ("device_id" , []))
8786 entity_ids = call .data .get ("entity_id" , [])
@@ -110,6 +109,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
110109
111110 hass .data .setdefault (DOMAIN , {})
112111 hass .data [DOMAIN ][entry .unique_id ] = hon
112+ hass .data [DOMAIN ].setdefault (SERVICE_REGISTRY , set ())
113113
114114 for appliance in hon .appliances :
115115
@@ -130,12 +130,12 @@ async def handle_oven_start(call):
130130
131131 if "start" in call .data :
132132 date = datetime .strptime (call .data .get ("start" ), "%Y-%m-%d %H:%M:%S" ).replace (tzinfo = tz )
133- delay_time = int (( date - datetime .now (tz )). seconds / 60 )
133+ delay_time = _minutes_until ( date , datetime .now (tz ))
134134
135135 if "end" in call .data and "duration" in call .data :
136136 date = datetime .strptime (call .data .get ("end" ), "%Y-%m-%d %H:%M:%S" ).replace (tzinfo = tz )
137137 duration = call .data .get ("duration" )
138- delay_time = int ( (date - datetime .now (tz )). seconds / 60 - duration )
138+ delay_time = max ( 0 , _minutes_until (date , datetime .now (tz )) - duration )
139139
140140 parameters = {
141141 "delayTime" : delay_time ,
@@ -161,12 +161,12 @@ async def handle_dishwasher_start(call):
161161
162162 if "start" in call .data :
163163 date = datetime .strptime (call .data .get ("start" ), "%Y-%m-%d %H:%M:%S" ).replace (tzinfo = tz )
164- delay_time = int (( date - datetime .now (tz )). seconds / 60 )
164+ delay_time = _minutes_until ( date , datetime .now (tz ))
165165
166166 if "end" in call .data and "duration" in call .data :
167167 date = datetime .strptime (call .data .get ("end" ), "%Y-%m-%d %H:%M:%S" ).replace (tzinfo = tz )
168168 duration = call .data .get ("duration" )
169- delay_time = int ( (date - datetime .now (tz )). seconds / 60 - duration )
169+ delay_time = max ( 0 , _minutes_until (date , datetime .now (tz )) - duration )
170170
171171 parameters = {
172172 "delayTime" : delay_time ,
@@ -190,7 +190,7 @@ async def handle_washingmachine_start(call):
190190 tz = gettz (hass .config .time_zone )
191191 if "end" in call .data :
192192 date = datetime .strptime (call .data .get ("end" ), "%Y-%m-%d %H:%M:%S" ).replace (tzinfo = tz )
193- delay_time = int (( date - datetime .now (tz )). seconds / 60 )
193+ delay_time = _minutes_until ( date , datetime .now (tz ))
194194
195195 parameters = {
196196 "haier_MainWashSpeed" : "50" ,
@@ -447,29 +447,57 @@ async def async_get_setting(call: ServiceCall):
447447
448448
449449
450- hass .services .async_register (DOMAIN , "turn_on_washingmachine" , handle_washingmachine_start )
451- hass .services .async_register (DOMAIN , "turn_on_oven" , handle_oven_start )
452- hass .services .async_register (DOMAIN , "turn_on_dishwasher" , handle_dishwasher_start )
453- hass .services .async_register (DOMAIN , "turn_on_purifier" , handle_purifier_start )
454- hass .services .async_register (DOMAIN , "set_auto_mode_purifier" , handle_purifier_automode )
455- hass .services .async_register (DOMAIN , "set_sleep_mode_purifier" , handle_purifier_sleepmode )
456- hass .services .async_register (DOMAIN , "set_max_mode_purifier" , handle_purifier_maxmode )
457-
458- hass .services .async_register (DOMAIN , "set_mode" , handle_set_mode )
459- hass .services .async_register (DOMAIN , "turn_off" , handle_turn_off )
460- hass .services .async_register (DOMAIN , "turn_light_on" , handle_light_on )
461- hass .services .async_register (DOMAIN , "turn_light_off" , handle_light_off )
462- hass .services .async_register (DOMAIN , "send_custom_request" , handle_custom_request )
463- hass .services .async_register (DOMAIN , "climate_turn_health_mode_on" , handle_health_mode_on )
464- hass .services .async_register (DOMAIN , "climate_turn_health_mode_off" , handle_health_mode_off )
465-
466- hass .services .async_register (DOMAIN , "start_program" , handle_start_program )
467- hass .services .async_register (DOMAIN , "update_settings" , handle_update_settings )
468- hass .services .async_register (
469- domain = DOMAIN ,
470- service = "get_setting" ,
471- service_func = async_get_setting ,
472- schema = None
473- )
450+ services = {
451+ "turn_on_washingmachine" : handle_washingmachine_start ,
452+ "turn_on_oven" : handle_oven_start ,
453+ "turn_on_dishwasher" : handle_dishwasher_start ,
454+ "turn_on_purifier" : handle_purifier_start ,
455+ "set_auto_mode_purifier" : handle_purifier_automode ,
456+ "set_sleep_mode_purifier" : handle_purifier_sleepmode ,
457+ "set_max_mode_purifier" : handle_purifier_maxmode ,
458+ "set_mode" : handle_set_mode ,
459+ "turn_off" : handle_turn_off ,
460+ "turn_light_on" : handle_light_on ,
461+ "turn_light_off" : handle_light_off ,
462+ "send_custom_request" : handle_custom_request ,
463+ "climate_turn_health_mode_on" : handle_health_mode_on ,
464+ "climate_turn_health_mode_off" : handle_health_mode_off ,
465+ "start_program" : handle_start_program ,
466+ "update_settings" : handle_update_settings ,
467+ "get_setting" : async_get_setting ,
468+ }
469+
470+ registered_services = hass .data [DOMAIN ][SERVICE_REGISTRY ]
471+ for service_name , handler in services .items ():
472+ if service_name in registered_services :
473+ continue
474+ hass .services .async_register (
475+ domain = DOMAIN ,
476+ service = service_name ,
477+ service_func = handler ,
478+ schema = None ,
479+ )
480+ registered_services .add (service_name )
481+
482+ return True
483+
484+
485+ async def async_unload_entry (hass : HomeAssistant , entry : ConfigEntry ) -> bool :
486+ """Unload a config entry."""
487+ unload_ok = await hass .config_entries .async_unload_platforms (entry , PLATFORMS )
488+ if not unload_ok :
489+ return False
490+
491+ hon = hass .data [DOMAIN ].pop (entry .unique_id , None )
492+ if hon is not None :
493+ await hon .async_close ()
494+
495+ remaining_entries = [
496+ key for key in hass .data .get (DOMAIN , {}) if key != SERVICE_REGISTRY
497+ ]
498+ if not remaining_entries :
499+ for service_name in hass .data [DOMAIN ].get (SERVICE_REGISTRY , set ()):
500+ hass .services .async_remove (DOMAIN , service_name )
501+ hass .data .pop (DOMAIN , None )
474502
475503 return True
0 commit comments