Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump hahomematic to 2024.9.3 #718

Merged
merged 4 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,19 @@ Returns a dict of link partners
Call to `getParamset` on the XML-RPC interface.
Returns a paramset

### `homematicip_local.get_link_paramset`

Call to `getParamset` for links on the XML-RPC interface.
Returns a paramset

### `homematicip_local.put_paramset`

Call to `putParamset` on the XML-RPC interface.

### `homematicip_local.put_link_paramset`

Call to `putParamset` for links on the XML-RPC interface.

### `homematicip_local.set_cover_combined_position`

Move a blind to a specific position and tilt position.
Expand Down
2 changes: 1 addition & 1 deletion changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Version 1.66.0 (2024-09-01)

- Bump hahomematic to 2024.9.1
- Bump hahomematic to 2024.9.3
- Add check for link paramsets
- Add getLinkPeers XmlRPC method
- Add paramset_key to entity_key
Expand Down
6 changes: 5 additions & 1 deletion custom_components/homematicip_local/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,11 @@
SERVICE_FETCH_SYSTEM_VARIABLES: Final = "fetch_system_variables"
SERVICE_FORCE_DEVICE_AVAILABILITY: Final = "force_device_availability"
SERVICE_GET_DEVICE_VALUE: Final = "get_device_value"
SERVICE_GET_LINK_PARAMSET: Final = "get_link_paramset"
SERVICE_GET_LINK_PEERS: Final = "get_link_peers"
SERVICE_GET_PARAMSET: Final = "get_paramset"
SERVICE_LIGHT_SET_ON_TIME: Final = "light_set_on_time"
SERVICE_PUT_LINK_PARAMSET: Final = "put_link_paramset"
SERVICE_PUT_PARAMSET: Final = "put_paramset"
SERVICE_SET_COVER_COMBINED_POSITION: Final = "set_cover_combined_position"
SERVICE_SET_DEVICE_VALUE: Final = "set_device_value"
Expand All @@ -81,9 +83,11 @@
SERVICE_FETCH_SYSTEM_VARIABLES,
SERVICE_FORCE_DEVICE_AVAILABILITY,
SERVICE_GET_DEVICE_VALUE,
SERVICE_GET_LINK_PARAMSET,
SERVICE_GET_LINK_PEERS,
SERVICE_GET_PARAMSET,
SERVICE_LIGHT_SET_ON_TIME,
SERVICE_GET_LINK_PEERS,
SERVICE_PUT_LINK_PARAMSET,
SERVICE_PUT_PARAMSET,
SERVICE_SET_COVER_COMBINED_POSITION,
SERVICE_SET_DEVICE_VALUE,
Expand Down
2 changes: 1 addition & 1 deletion custom_components/homematicip_local/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"iot_class": "local_push",
"issue_tracker": "https://github.com/danielperna84/hahomematic/issues",
"loggers": ["hahomematic"],
"requirements": ["hahomematic==2024.9.1"],
"requirements": ["hahomematic==2024.9.3"],
"ssdp": [
{
"manufacturer": "EQ3",
Expand Down
119 changes: 105 additions & 14 deletions custom_components/homematicip_local/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from hahomematic.const import ForcedDeviceAvailability, ParamsetKey
from hahomematic.exceptions import ClientException
from hahomematic.platforms.device import HmDevice
from hahomematic.support import to_bool
from hahomematic.support import get_device_address, to_bool
import hahomematic.validator as hmval
import voluptuous as vol

from homeassistant.config_entries import ConfigEntryState
Expand All @@ -35,8 +36,10 @@
SERVICE_FETCH_SYSTEM_VARIABLES,
SERVICE_FORCE_DEVICE_AVAILABILITY,
SERVICE_GET_DEVICE_VALUE,
SERVICE_GET_LINK_PARAMSET,
SERVICE_GET_LINK_PEERS,
SERVICE_GET_PARAMSET,
SERVICE_PUT_LINK_PARAMSET,
SERVICE_PUT_PARAMSET,
SERVICE_SET_DEVICE_VALUE,
SERVICE_SET_INSTALL_MODE,
Expand All @@ -53,7 +56,7 @@

CONF_ADDRESS: Final = "address"
CONF_CHANNEL: Final = "channel"
CONF_TIME: Final = "time"
CONF_CHANNEL_ADDRESS: Final = "channel_address"
CONF_DEVICE_ADDRESS: Final = "device_address"
CONF_ENTRY_ID: Final = "entry_id"
CONF_INTERFACE_ID: Final = "interface_id"
Expand All @@ -62,6 +65,8 @@
CONF_PARAMSET: Final = "paramset"
CONF_PARAMSET_KEY: Final = "paramset_key"
CONF_RX_MODE: Final = "rx_mode"
CONF_SENDER_CHANNEL_ADDRESS: Final = "sender_channel_address"
CONF_TIME: Final = "time"
CONF_VALUE: Final = "value"
CONF_VALUE_TYPE: Final = "value_type"
CONF_WAIT_FOR_CALLBACK: Final = "wait_for_callback"
Expand All @@ -71,7 +76,7 @@
BASE_SCHEMA_DEVICE = vol.Schema(
{
vol.Optional(CONF_DEVICE_ID): cv.string,
vol.Optional(CONF_DEVICE_ADDRESS): cv.string,
vol.Optional(CONF_DEVICE_ADDRESS): hmval.device_address,
}
)

Expand Down Expand Up @@ -105,7 +110,7 @@
cv.has_at_most_one_key(CONF_DEVICE_ID, CONF_DEVICE_ADDRESS),
BASE_SCHEMA_DEVICE.extend(
{
vol.Required(CONF_CHANNEL, default=DEFAULT_CHANNEL): vol.Coerce(int),
vol.Required(CONF_CHANNEL, default=DEFAULT_CHANNEL): hmval.channel_no,
vol.Required(CONF_PARAMETER): vol.All(cv.string, vol.Upper),
}
),
Expand All @@ -116,18 +121,25 @@
cv.has_at_most_one_key(CONF_DEVICE_ID, CONF_DEVICE_ADDRESS),
BASE_SCHEMA_DEVICE.extend(
{
vol.Optional(CONF_CHANNEL): vol.Coerce(int),
vol.Optional(CONF_CHANNEL): hmval.channel_no,
}
),
)

SCHEMA_SERVICE_GET_LINK_PARAMSET = vol.All(
{
vol.Optional(CONF_CHANNEL_ADDRESS): hmval.channel_address,
vol.Optional(CONF_SENDER_CHANNEL_ADDRESS): hmval.channel_address,
}
)

SCHEMA_SERVICE_GET_PARAMSET = vol.All(
cv.has_at_least_one_key(CONF_DEVICE_ID, CONF_DEVICE_ADDRESS),
cv.has_at_most_one_key(CONF_DEVICE_ID, CONF_DEVICE_ADDRESS),
BASE_SCHEMA_DEVICE.extend(
{
vol.Optional(CONF_CHANNEL): vol.Coerce(int),
vol.Required(CONF_PARAMSET_KEY): vol.All(cv.string, vol.Upper),
vol.Optional(CONF_CHANNEL): hmval.channel_no,
vol.Required(CONF_PARAMSET_KEY): vol.In(["MASTER", "VALUES"]),
}
),
)
Expand All @@ -145,7 +157,7 @@
vol.Required(CONF_INTERFACE_ID): cv.string,
vol.Optional(CONF_TIME, default=60): cv.positive_int,
vol.Optional(CONF_MODE, default=1): vol.All(vol.Coerce(int), vol.In([1, 2])),
vol.Optional(CONF_ADDRESS): vol.All(cv.string, vol.Upper),
vol.Optional(CONF_ADDRESS): hmval.device_address,
}
)

Expand All @@ -154,10 +166,10 @@
cv.has_at_most_one_key(CONF_DEVICE_ID, CONF_DEVICE_ADDRESS),
BASE_SCHEMA_DEVICE.extend(
{
vol.Required(CONF_CHANNEL, default=DEFAULT_CHANNEL): vol.Coerce(int),
vol.Required(CONF_CHANNEL, default=DEFAULT_CHANNEL): hmval.channel_no,
vol.Required(CONF_PARAMETER): vol.All(cv.string, vol.Upper),
vol.Required(CONF_VALUE): cv.match_all,
vol.Optional(CONF_WAIT_FOR_CALLBACK): cv.positive_int,
vol.Optional(CONF_WAIT_FOR_CALLBACK): hmval.wait_for,
vol.Optional(CONF_VALUE_TYPE): vol.In(
["boolean", "dateTime.iso8601", "double", "int", "string"]
),
Expand All @@ -166,15 +178,24 @@
),
)

SCHEMA_SERVICE_PUT_LINK_PARAMSET = vol.All(
{
vol.Optional(CONF_CHANNEL_ADDRESS): hmval.channel_address,
vol.Optional(CONF_SENDER_CHANNEL_ADDRESS): hmval.channel_address,
vol.Required(CONF_PARAMSET): dict,
vol.Optional(CONF_RX_MODE): vol.All(cv.string, vol.Upper),
}
)

SCHEMA_SERVICE_PUT_PARAMSET = vol.All(
cv.has_at_least_one_key(CONF_DEVICE_ID, CONF_DEVICE_ADDRESS),
cv.has_at_most_one_key(CONF_DEVICE_ID, CONF_DEVICE_ADDRESS),
BASE_SCHEMA_DEVICE.extend(
{
vol.Optional(CONF_CHANNEL): vol.Coerce(int),
vol.Required(CONF_PARAMSET_KEY): vol.All(cv.string, vol.Upper),
vol.Optional(CONF_CHANNEL): hmval.channel_no,
vol.Required(CONF_PARAMSET_KEY): vol.In(["MASTER", "VALUES"]),
vol.Required(CONF_PARAMSET): dict,
vol.Optional(CONF_WAIT_FOR_CALLBACK): cv.positive_int,
vol.Optional(CONF_WAIT_FOR_CALLBACK): hmval.wait_for,
vol.Optional(CONF_RX_MODE): vol.All(cv.string, vol.Upper),
}
),
Expand Down Expand Up @@ -207,8 +228,12 @@ async def async_call_hmip_local_service(service: ServiceCall) -> ServiceResponse
return await _async_service_get_device_value(hass=hass, service=service)
elif service_name == SERVICE_GET_LINK_PEERS:
return await _async_service_get_link_peers(hass=hass, service=service)
elif service_name == SERVICE_GET_LINK_PARAMSET:
return await _async_service_get_link_paramset(hass=hass, service=service)
elif service_name == SERVICE_GET_PARAMSET:
return await _async_service_get_paramset(hass=hass, service=service)
elif service_name == SERVICE_PUT_LINK_PARAMSET:
await _async_service_put_link_paramset(hass=hass, service=service)
elif service_name == SERVICE_PUT_PARAMSET:
await _async_service_put_paramset(hass=hass, service=service)
elif service_name == SERVICE_SET_INSTALL_MODE:
Expand Down Expand Up @@ -269,6 +294,14 @@ async def async_call_hmip_local_service(service: ServiceCall) -> ServiceResponse
supports_response=SupportsResponse.OPTIONAL,
)

hass.services.async_register(
domain=DOMAIN,
service=SERVICE_GET_LINK_PARAMSET,
service_func=async_call_hmip_local_service,
schema=SCHEMA_SERVICE_GET_LINK_PARAMSET,
supports_response=SupportsResponse.OPTIONAL,
)

hass.services.async_register(
domain=DOMAIN,
service=SERVICE_GET_PARAMSET,
Expand Down Expand Up @@ -299,6 +332,13 @@ async def async_call_hmip_local_service(service: ServiceCall) -> ServiceResponse
schema=SCHEMA_SERVICE_SET_INSTALL_MODE,
)

hass.services.async_register(
domain=DOMAIN,
service=SERVICE_PUT_LINK_PARAMSET,
service_func=async_call_hmip_local_service,
schema=SCHEMA_SERVICE_PUT_LINK_PARAMSET,
)

hass.services.async_register(
domain=DOMAIN,
service=SERVICE_PUT_PARAMSET,
Expand Down Expand Up @@ -395,12 +435,33 @@ async def _async_service_get_link_peers(
return None


async def _async_service_get_link_paramset(
hass: HomeAssistant, service: ServiceCall
) -> ServiceResponse:
"""Service to call the getParamset method for links on a Homematic(IP) Local connection."""
channel_address = service.data[CONF_CHANNEL_ADDRESS]
sender_channel_address = service.data[CONF_SENDER_CHANNEL_ADDRESS]

if hm_device := _async_get_hm_device_by_service_data(hass=hass, service=service):
try:
return dict(
await hm_device.client.get_paramset(
address=channel_address,
paramset_key=sender_channel_address,
)
)
except ClientException as cex:
raise HomeAssistantError(cex) from cex

return None


async def _async_service_get_paramset(
hass: HomeAssistant, service: ServiceCall
) -> ServiceResponse:
"""Service to call the getParamset method on a Homematic(IP) Local connection."""
channel_no = service.data.get(CONF_CHANNEL)
paramset_key = ParamsetKey(service.data[CONF_PARAMSET_KEY])
paramset_key = service.data[CONF_PARAMSET_KEY]

if hm_device := _async_get_hm_device_by_service_data(hass=hass, service=service):
address = (
Expand Down Expand Up @@ -493,6 +554,25 @@ async def _async_service_fetch_system_variables(hass: HomeAssistant, service: Se
await control.fetch_all_system_variables()


async def _async_service_put_link_paramset(hass: HomeAssistant, service: ServiceCall) -> None:
"""Service to call the putParamset method for link manipulation on a Homematic(IP) Local connection."""
channel_address = service.data[CONF_CHANNEL_ADDRESS]
sender_channel_address = service.data[CONF_SENDER_CHANNEL_ADDRESS]
# When passing in the paramset from a YAML file we get an OrderedDict
# here instead of a dict, so add this explicit cast.
# The service schema makes sure that this cast works.
values = dict(service.data[CONF_PARAMSET])
rx_mode = service.data.get(CONF_RX_MODE)

if hm_device := _async_get_hm_device_by_service_data(hass=hass, service=service):
await hm_device.client.put_paramset(
channel_address=channel_address,
paramset_key=sender_channel_address,
values=values,
rx_mode=rx_mode,
)


async def _async_service_put_paramset(hass: HomeAssistant, service: ServiceCall) -> None:
"""Service to call the putParamset method on a Homematic(IP) Local connection."""
channel_no = service.data.get(CONF_CHANNEL)
Expand Down Expand Up @@ -564,6 +644,17 @@ def _async_get_hm_device_by_service_data(
service.domain,
service.service,
)
elif channel_address := service.data.get(CONF_CHANNEL_ADDRESS):
hm_device = _async_get_hm_device_by_address(
hass=hass, device_address=get_device_address(address=channel_address)
)
if not hm_device:
_LOGGER.warning(
"No device found by channel_address %s for service %s.%s",
device_address,
service.domain,
service.service,
)

return hm_device

Expand Down
39 changes: 39 additions & 0 deletions custom_components/homematicip_local/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,19 @@ get_link_peers:
min: 0
max: 99

get_link_paramset:
fields:
channel_address:
example: "0008789453:3"
required: true
selector:
text:
sender_channel_address:
example: "0008789453:3"
required: true
selector:
text:

get_paramset:
fields:
device_id:
Expand All @@ -106,6 +119,7 @@ get_paramset:
options:
- "MASTER"
- "VALUES"

set_variable_value:
fields:
entry_id:
Expand Down Expand Up @@ -200,6 +214,31 @@ set_install_mode:
selector:
text:

put_link_paramset:
fields:
channel_address:
example: "0008789453:3"
required: true
selector:
text:
sender_channel_address:
example: "0008789453:3"
required: true
selector:
text:
paramset:
required: true
example: '{"WEEK_PROGRAM_POINTER": 1}'
selector:
object:
rx_mode:
example: BURST
selector:
select:
options:
- "BURST"
- "WAKEUP"

put_paramset:
fields:
device_id:
Expand Down
Loading