aiohomematic 2026.1.29__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aiohomematic/__init__.py +110 -0
- aiohomematic/_log_context_protocol.py +29 -0
- aiohomematic/api.py +410 -0
- aiohomematic/async_support.py +250 -0
- aiohomematic/backend_detection.py +462 -0
- aiohomematic/central/__init__.py +103 -0
- aiohomematic/central/async_rpc_server.py +760 -0
- aiohomematic/central/central_unit.py +1152 -0
- aiohomematic/central/config.py +463 -0
- aiohomematic/central/config_builder.py +772 -0
- aiohomematic/central/connection_state.py +160 -0
- aiohomematic/central/coordinators/__init__.py +38 -0
- aiohomematic/central/coordinators/cache.py +414 -0
- aiohomematic/central/coordinators/client.py +480 -0
- aiohomematic/central/coordinators/connection_recovery.py +1141 -0
- aiohomematic/central/coordinators/device.py +1166 -0
- aiohomematic/central/coordinators/event.py +514 -0
- aiohomematic/central/coordinators/hub.py +532 -0
- aiohomematic/central/decorators.py +184 -0
- aiohomematic/central/device_registry.py +229 -0
- aiohomematic/central/events/__init__.py +104 -0
- aiohomematic/central/events/bus.py +1392 -0
- aiohomematic/central/events/integration.py +424 -0
- aiohomematic/central/events/types.py +194 -0
- aiohomematic/central/health.py +762 -0
- aiohomematic/central/rpc_server.py +353 -0
- aiohomematic/central/scheduler.py +794 -0
- aiohomematic/central/state_machine.py +391 -0
- aiohomematic/client/__init__.py +203 -0
- aiohomematic/client/_rpc_errors.py +187 -0
- aiohomematic/client/backends/__init__.py +48 -0
- aiohomematic/client/backends/base.py +335 -0
- aiohomematic/client/backends/capabilities.py +138 -0
- aiohomematic/client/backends/ccu.py +487 -0
- aiohomematic/client/backends/factory.py +116 -0
- aiohomematic/client/backends/homegear.py +294 -0
- aiohomematic/client/backends/json_ccu.py +252 -0
- aiohomematic/client/backends/protocol.py +316 -0
- aiohomematic/client/ccu.py +1857 -0
- aiohomematic/client/circuit_breaker.py +459 -0
- aiohomematic/client/config.py +64 -0
- aiohomematic/client/handlers/__init__.py +40 -0
- aiohomematic/client/handlers/backup.py +157 -0
- aiohomematic/client/handlers/base.py +79 -0
- aiohomematic/client/handlers/device_ops.py +1085 -0
- aiohomematic/client/handlers/firmware.py +144 -0
- aiohomematic/client/handlers/link_mgmt.py +199 -0
- aiohomematic/client/handlers/metadata.py +436 -0
- aiohomematic/client/handlers/programs.py +144 -0
- aiohomematic/client/handlers/sysvars.py +100 -0
- aiohomematic/client/interface_client.py +1304 -0
- aiohomematic/client/json_rpc.py +2068 -0
- aiohomematic/client/request_coalescer.py +282 -0
- aiohomematic/client/rpc_proxy.py +629 -0
- aiohomematic/client/state_machine.py +324 -0
- aiohomematic/const.py +2207 -0
- aiohomematic/context.py +275 -0
- aiohomematic/converter.py +270 -0
- aiohomematic/decorators.py +390 -0
- aiohomematic/exceptions.py +185 -0
- aiohomematic/hmcli.py +997 -0
- aiohomematic/i18n.py +193 -0
- aiohomematic/interfaces/__init__.py +407 -0
- aiohomematic/interfaces/central.py +1067 -0
- aiohomematic/interfaces/client.py +1096 -0
- aiohomematic/interfaces/coordinators.py +63 -0
- aiohomematic/interfaces/model.py +1921 -0
- aiohomematic/interfaces/operations.py +217 -0
- aiohomematic/logging_context.py +134 -0
- aiohomematic/metrics/__init__.py +125 -0
- aiohomematic/metrics/_protocols.py +140 -0
- aiohomematic/metrics/aggregator.py +534 -0
- aiohomematic/metrics/dataclasses.py +489 -0
- aiohomematic/metrics/emitter.py +292 -0
- aiohomematic/metrics/events.py +183 -0
- aiohomematic/metrics/keys.py +300 -0
- aiohomematic/metrics/observer.py +563 -0
- aiohomematic/metrics/stats.py +172 -0
- aiohomematic/model/__init__.py +189 -0
- aiohomematic/model/availability.py +65 -0
- aiohomematic/model/calculated/__init__.py +89 -0
- aiohomematic/model/calculated/climate.py +276 -0
- aiohomematic/model/calculated/data_point.py +315 -0
- aiohomematic/model/calculated/field.py +147 -0
- aiohomematic/model/calculated/operating_voltage_level.py +286 -0
- aiohomematic/model/calculated/support.py +232 -0
- aiohomematic/model/custom/__init__.py +214 -0
- aiohomematic/model/custom/capabilities/__init__.py +67 -0
- aiohomematic/model/custom/capabilities/climate.py +41 -0
- aiohomematic/model/custom/capabilities/light.py +87 -0
- aiohomematic/model/custom/capabilities/lock.py +44 -0
- aiohomematic/model/custom/capabilities/siren.py +63 -0
- aiohomematic/model/custom/climate.py +1130 -0
- aiohomematic/model/custom/cover.py +722 -0
- aiohomematic/model/custom/data_point.py +360 -0
- aiohomematic/model/custom/definition.py +300 -0
- aiohomematic/model/custom/field.py +89 -0
- aiohomematic/model/custom/light.py +1174 -0
- aiohomematic/model/custom/lock.py +322 -0
- aiohomematic/model/custom/mixins.py +445 -0
- aiohomematic/model/custom/profile.py +945 -0
- aiohomematic/model/custom/registry.py +251 -0
- aiohomematic/model/custom/siren.py +462 -0
- aiohomematic/model/custom/switch.py +195 -0
- aiohomematic/model/custom/text_display.py +289 -0
- aiohomematic/model/custom/valve.py +78 -0
- aiohomematic/model/data_point.py +1416 -0
- aiohomematic/model/device.py +1840 -0
- aiohomematic/model/event.py +216 -0
- aiohomematic/model/generic/__init__.py +327 -0
- aiohomematic/model/generic/action.py +40 -0
- aiohomematic/model/generic/action_select.py +62 -0
- aiohomematic/model/generic/binary_sensor.py +30 -0
- aiohomematic/model/generic/button.py +31 -0
- aiohomematic/model/generic/data_point.py +177 -0
- aiohomematic/model/generic/dummy.py +150 -0
- aiohomematic/model/generic/number.py +76 -0
- aiohomematic/model/generic/select.py +56 -0
- aiohomematic/model/generic/sensor.py +76 -0
- aiohomematic/model/generic/switch.py +54 -0
- aiohomematic/model/generic/text.py +33 -0
- aiohomematic/model/hub/__init__.py +100 -0
- aiohomematic/model/hub/binary_sensor.py +24 -0
- aiohomematic/model/hub/button.py +28 -0
- aiohomematic/model/hub/connectivity.py +190 -0
- aiohomematic/model/hub/data_point.py +342 -0
- aiohomematic/model/hub/hub.py +864 -0
- aiohomematic/model/hub/inbox.py +135 -0
- aiohomematic/model/hub/install_mode.py +393 -0
- aiohomematic/model/hub/metrics.py +208 -0
- aiohomematic/model/hub/number.py +42 -0
- aiohomematic/model/hub/select.py +52 -0
- aiohomematic/model/hub/sensor.py +37 -0
- aiohomematic/model/hub/switch.py +43 -0
- aiohomematic/model/hub/text.py +30 -0
- aiohomematic/model/hub/update.py +221 -0
- aiohomematic/model/support.py +592 -0
- aiohomematic/model/update.py +140 -0
- aiohomematic/model/week_profile.py +1827 -0
- aiohomematic/property_decorators.py +719 -0
- aiohomematic/py.typed +0 -0
- aiohomematic/rega_scripts/accept_device_in_inbox.fn +51 -0
- aiohomematic/rega_scripts/create_backup_start.fn +28 -0
- aiohomematic/rega_scripts/create_backup_status.fn +89 -0
- aiohomematic/rega_scripts/fetch_all_device_data.fn +97 -0
- aiohomematic/rega_scripts/get_backend_info.fn +25 -0
- aiohomematic/rega_scripts/get_inbox_devices.fn +61 -0
- aiohomematic/rega_scripts/get_program_descriptions.fn +31 -0
- aiohomematic/rega_scripts/get_serial.fn +44 -0
- aiohomematic/rega_scripts/get_service_messages.fn +83 -0
- aiohomematic/rega_scripts/get_system_update_info.fn +39 -0
- aiohomematic/rega_scripts/get_system_variable_descriptions.fn +31 -0
- aiohomematic/rega_scripts/set_program_state.fn +17 -0
- aiohomematic/rega_scripts/set_system_variable.fn +19 -0
- aiohomematic/rega_scripts/trigger_firmware_update.fn +67 -0
- aiohomematic/schemas.py +256 -0
- aiohomematic/store/__init__.py +55 -0
- aiohomematic/store/dynamic/__init__.py +43 -0
- aiohomematic/store/dynamic/command.py +250 -0
- aiohomematic/store/dynamic/data.py +175 -0
- aiohomematic/store/dynamic/details.py +187 -0
- aiohomematic/store/dynamic/ping_pong.py +416 -0
- aiohomematic/store/persistent/__init__.py +71 -0
- aiohomematic/store/persistent/base.py +285 -0
- aiohomematic/store/persistent/device.py +233 -0
- aiohomematic/store/persistent/incident.py +380 -0
- aiohomematic/store/persistent/paramset.py +241 -0
- aiohomematic/store/persistent/session.py +556 -0
- aiohomematic/store/serialization.py +150 -0
- aiohomematic/store/storage.py +689 -0
- aiohomematic/store/types.py +526 -0
- aiohomematic/store/visibility/__init__.py +40 -0
- aiohomematic/store/visibility/parser.py +141 -0
- aiohomematic/store/visibility/registry.py +722 -0
- aiohomematic/store/visibility/rules.py +307 -0
- aiohomematic/strings.json +237 -0
- aiohomematic/support.py +706 -0
- aiohomematic/tracing.py +236 -0
- aiohomematic/translations/de.json +237 -0
- aiohomematic/translations/en.json +237 -0
- aiohomematic/type_aliases.py +51 -0
- aiohomematic/validator.py +128 -0
- aiohomematic-2026.1.29.dist-info/METADATA +296 -0
- aiohomematic-2026.1.29.dist-info/RECORD +188 -0
- aiohomematic-2026.1.29.dist-info/WHEEL +5 -0
- aiohomematic-2026.1.29.dist-info/entry_points.txt +2 -0
- aiohomematic-2026.1.29.dist-info/licenses/LICENSE +21 -0
- aiohomematic-2026.1.29.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2026
|
|
3
|
+
"""
|
|
4
|
+
Hub (backend) data points for AioHomematic.
|
|
5
|
+
|
|
6
|
+
This package reflects the state and capabilities of the backend at the hub
|
|
7
|
+
level. It exposes backend programs, system variables, install mode, metrics,
|
|
8
|
+
and system updates as data points that can be observed and acted upon by
|
|
9
|
+
higher layers (e.g., Home Assistant integration).
|
|
10
|
+
|
|
11
|
+
Package structure
|
|
12
|
+
-----------------
|
|
13
|
+
- hub.py: Hub orchestrator class and container types (ProgramDpType, MetricsDpType)
|
|
14
|
+
- data_point.py: Base classes (GenericHubDataPoint, GenericProgramDataPoint, GenericSysvarDataPoint)
|
|
15
|
+
- button.py, switch.py: Program data points (ProgramDpButton, ProgramDpSwitch)
|
|
16
|
+
- sensor.py, binary_sensor.py, select.py, number.py, text.py: Sysvar data points
|
|
17
|
+
- install_mode.py: Install mode button and sensor
|
|
18
|
+
- metrics.py: System health, connection latency, event age sensors
|
|
19
|
+
- inbox.py: Inbox device sensor
|
|
20
|
+
- update.py: System update sensor
|
|
21
|
+
|
|
22
|
+
Public API
|
|
23
|
+
----------
|
|
24
|
+
- Hub: Main orchestrator for hub-level data point lifecycle
|
|
25
|
+
- Program data points: ProgramDpButton, ProgramDpSwitch, ProgramDpType
|
|
26
|
+
- Sysvar data points: SysvarDpSensor, SysvarDpBinarySensor, SysvarDpSelect,
|
|
27
|
+
SysvarDpNumber, SysvarDpSwitch, SysvarDpText
|
|
28
|
+
- Install mode: InstallModeDpButton, InstallModeDpSensor, InstallModeDpType
|
|
29
|
+
- Metrics: HmSystemHealthSensor, HmConnectionLatencySensor, HmLastEventAgeSensor, MetricsDpType
|
|
30
|
+
- Other: HmInboxSensor, HmUpdate
|
|
31
|
+
- Base types: GenericHubDataPoint, GenericProgramDataPoint, GenericSysvarDataPoint
|
|
32
|
+
|
|
33
|
+
Sysvar type mapping
|
|
34
|
+
-------------------
|
|
35
|
+
System variables are mapped to data point types based on SysvarType:
|
|
36
|
+
- ALARM/LOGIC → SysvarDpBinarySensor (or SysvarDpSwitch if extended)
|
|
37
|
+
- LIST (extended) → SysvarDpSelect
|
|
38
|
+
- FLOAT/INTEGER (extended) → SysvarDpNumber
|
|
39
|
+
- STRING (extended) → SysvarDpText
|
|
40
|
+
- Other → SysvarDpSensor
|
|
41
|
+
|
|
42
|
+
Related modules
|
|
43
|
+
---------------
|
|
44
|
+
- aiohomematic.central: Central unit coordination
|
|
45
|
+
- aiohomematic.const: HUB_CATEGORIES, SystemEventType.HUB_REFRESHED
|
|
46
|
+
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
from __future__ import annotations
|
|
50
|
+
|
|
51
|
+
from aiohomematic.model.hub.binary_sensor import SysvarDpBinarySensor
|
|
52
|
+
from aiohomematic.model.hub.button import ProgramDpButton
|
|
53
|
+
from aiohomematic.model.hub.connectivity import HmInterfaceConnectivitySensor
|
|
54
|
+
from aiohomematic.model.hub.data_point import GenericHubDataPoint, GenericProgramDataPoint, GenericSysvarDataPoint
|
|
55
|
+
from aiohomematic.model.hub.hub import ConnectivityDpType, Hub, MetricsDpType, ProgramDpType
|
|
56
|
+
from aiohomematic.model.hub.inbox import HmInboxSensor
|
|
57
|
+
from aiohomematic.model.hub.install_mode import InstallModeDpButton, InstallModeDpSensor, InstallModeDpType
|
|
58
|
+
from aiohomematic.model.hub.metrics import HmConnectionLatencySensor, HmLastEventAgeSensor, HmSystemHealthSensor
|
|
59
|
+
from aiohomematic.model.hub.number import SysvarDpNumber
|
|
60
|
+
from aiohomematic.model.hub.select import SysvarDpSelect
|
|
61
|
+
from aiohomematic.model.hub.sensor import SysvarDpSensor
|
|
62
|
+
from aiohomematic.model.hub.switch import ProgramDpSwitch, SysvarDpSwitch
|
|
63
|
+
from aiohomematic.model.hub.text import SysvarDpText
|
|
64
|
+
from aiohomematic.model.hub.update import HmUpdate
|
|
65
|
+
|
|
66
|
+
__all__ = [
|
|
67
|
+
# Base
|
|
68
|
+
"GenericHubDataPoint",
|
|
69
|
+
"GenericProgramDataPoint",
|
|
70
|
+
"GenericSysvarDataPoint",
|
|
71
|
+
# Connectivity
|
|
72
|
+
"ConnectivityDpType",
|
|
73
|
+
"HmInterfaceConnectivitySensor",
|
|
74
|
+
# Hub
|
|
75
|
+
"Hub",
|
|
76
|
+
# Inbox
|
|
77
|
+
"HmInboxSensor",
|
|
78
|
+
# Install mode
|
|
79
|
+
"InstallModeDpButton",
|
|
80
|
+
"InstallModeDpSensor",
|
|
81
|
+
"InstallModeDpType",
|
|
82
|
+
# Metrics
|
|
83
|
+
"HmConnectionLatencySensor",
|
|
84
|
+
"HmLastEventAgeSensor",
|
|
85
|
+
"HmSystemHealthSensor",
|
|
86
|
+
"MetricsDpType",
|
|
87
|
+
# Program
|
|
88
|
+
"ProgramDpButton",
|
|
89
|
+
"ProgramDpSwitch",
|
|
90
|
+
"ProgramDpType",
|
|
91
|
+
# Sysvar
|
|
92
|
+
"SysvarDpBinarySensor",
|
|
93
|
+
"SysvarDpNumber",
|
|
94
|
+
"SysvarDpSelect",
|
|
95
|
+
"SysvarDpSensor",
|
|
96
|
+
"SysvarDpSwitch",
|
|
97
|
+
"SysvarDpText",
|
|
98
|
+
# Update
|
|
99
|
+
"HmUpdate",
|
|
100
|
+
]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2026
|
|
3
|
+
"""Module for hub data points implemented using the binary_sensor category."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from aiohomematic.const import DataPointCategory
|
|
8
|
+
from aiohomematic.model.hub.data_point import GenericSysvarDataPoint
|
|
9
|
+
from aiohomematic.property_decorators import state_property
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SysvarDpBinarySensor(GenericSysvarDataPoint):
|
|
13
|
+
"""Implementation of a sysvar binary_sensor."""
|
|
14
|
+
|
|
15
|
+
__slots__ = ()
|
|
16
|
+
|
|
17
|
+
_category = DataPointCategory.HUB_BINARY_SENSOR
|
|
18
|
+
|
|
19
|
+
@state_property
|
|
20
|
+
def value(self) -> bool | None:
|
|
21
|
+
"""Return the value of the data_point."""
|
|
22
|
+
if self._value is not None:
|
|
23
|
+
return bool(self._value)
|
|
24
|
+
return None
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2026
|
|
3
|
+
"""Module for hub data points implemented using the button category."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from aiohomematic.const import DataPointCategory
|
|
8
|
+
from aiohomematic.decorators import inspector
|
|
9
|
+
from aiohomematic.model.hub.data_point import GenericProgramDataPoint
|
|
10
|
+
from aiohomematic.property_decorators import state_property
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ProgramDpButton(GenericProgramDataPoint):
|
|
14
|
+
"""Class for a Homematic program button."""
|
|
15
|
+
|
|
16
|
+
__slots__ = ()
|
|
17
|
+
|
|
18
|
+
_category = DataPointCategory.HUB_BUTTON
|
|
19
|
+
|
|
20
|
+
@state_property
|
|
21
|
+
def available(self) -> bool:
|
|
22
|
+
"""Return the availability of the device."""
|
|
23
|
+
return self._is_active and self._central_info.available
|
|
24
|
+
|
|
25
|
+
@inspector
|
|
26
|
+
async def press(self) -> None:
|
|
27
|
+
"""Handle the button press."""
|
|
28
|
+
await self._hub_data_fetcher.execute_program(pid=self.pid)
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2026
|
|
3
|
+
"""
|
|
4
|
+
Hub sensors for interface connectivity status.
|
|
5
|
+
|
|
6
|
+
This module provides binary sensor data points for monitoring the
|
|
7
|
+
connectivity status of each CCU interface. These sensors show whether
|
|
8
|
+
each interface is connected and operational.
|
|
9
|
+
|
|
10
|
+
Public API
|
|
11
|
+
----------
|
|
12
|
+
- HmInterfaceConnectivitySensor: Binary sensor showing interface connectivity
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
from datetime import datetime
|
|
18
|
+
import logging
|
|
19
|
+
from typing import TYPE_CHECKING, Final
|
|
20
|
+
|
|
21
|
+
from slugify import slugify
|
|
22
|
+
|
|
23
|
+
from aiohomematic.const import CONNECTIVITY_SENSOR_PREFIX, HUB_ADDRESS, DataPointCategory, HubValueType, Interface
|
|
24
|
+
from aiohomematic.interfaces import (
|
|
25
|
+
CentralInfoProtocol,
|
|
26
|
+
ChannelProtocol,
|
|
27
|
+
ConfigProviderProtocol,
|
|
28
|
+
EventBusProviderProtocol,
|
|
29
|
+
EventPublisherProtocol,
|
|
30
|
+
HealthTrackerProtocol,
|
|
31
|
+
HubBinarySensorDataPointProtocol,
|
|
32
|
+
ParameterVisibilityProviderProtocol,
|
|
33
|
+
ParamsetDescriptionProviderProtocol,
|
|
34
|
+
TaskSchedulerProtocol,
|
|
35
|
+
)
|
|
36
|
+
from aiohomematic.model.data_point import CallbackDataPoint
|
|
37
|
+
from aiohomematic.model.support import HubPathData, PathData, generate_unique_id, get_hub_data_point_name_data
|
|
38
|
+
from aiohomematic.property_decorators import DelegatedProperty, Kind, state_property
|
|
39
|
+
from aiohomematic.support import PayloadMixin
|
|
40
|
+
|
|
41
|
+
if TYPE_CHECKING:
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
_LOGGER: Final = logging.getLogger(__name__)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class HmInterfaceConnectivitySensor(CallbackDataPoint, HubBinarySensorDataPointProtocol, PayloadMixin):
|
|
48
|
+
"""
|
|
49
|
+
Binary sensor showing interface connectivity status.
|
|
50
|
+
|
|
51
|
+
This sensor provides a clear indication of whether a specific
|
|
52
|
+
interface (e.g., HmIP-RF, BidCos-RF) is connected and operational.
|
|
53
|
+
|
|
54
|
+
States:
|
|
55
|
+
- True (ON): Interface is connected and circuit breakers are closed
|
|
56
|
+
- False (OFF): Interface is disconnected, failed, or degraded
|
|
57
|
+
|
|
58
|
+
The sensor is always available (never shows unavailable) since its
|
|
59
|
+
purpose is to show the connection state itself.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
__slots__ = (
|
|
63
|
+
"_cached_value",
|
|
64
|
+
"_health_tracker",
|
|
65
|
+
"_interface",
|
|
66
|
+
"_interface_id",
|
|
67
|
+
"_name_data",
|
|
68
|
+
"_state_uncertain",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
_category = DataPointCategory.HUB_BINARY_SENSOR
|
|
72
|
+
_enabled_default = True
|
|
73
|
+
|
|
74
|
+
def __init__(
|
|
75
|
+
self,
|
|
76
|
+
*,
|
|
77
|
+
interface_id: str,
|
|
78
|
+
interface: Interface,
|
|
79
|
+
health_tracker: HealthTrackerProtocol,
|
|
80
|
+
config_provider: ConfigProviderProtocol,
|
|
81
|
+
central_info: CentralInfoProtocol,
|
|
82
|
+
event_bus_provider: EventBusProviderProtocol,
|
|
83
|
+
event_publisher: EventPublisherProtocol,
|
|
84
|
+
task_scheduler: TaskSchedulerProtocol,
|
|
85
|
+
paramset_description_provider: ParamsetDescriptionProviderProtocol,
|
|
86
|
+
parameter_visibility_provider: ParameterVisibilityProviderProtocol,
|
|
87
|
+
) -> None:
|
|
88
|
+
"""Initialize the connectivity sensor."""
|
|
89
|
+
PayloadMixin.__init__(self)
|
|
90
|
+
self._interface_id: Final = interface_id
|
|
91
|
+
self._interface: Final = interface
|
|
92
|
+
self._health_tracker: Final = health_tracker
|
|
93
|
+
|
|
94
|
+
# Create unique ID and name
|
|
95
|
+
sensor_name = f"{CONNECTIVITY_SENSOR_PREFIX} {interface.value}"
|
|
96
|
+
unique_id: Final = generate_unique_id(
|
|
97
|
+
config_provider=config_provider,
|
|
98
|
+
address=HUB_ADDRESS,
|
|
99
|
+
parameter=slugify(f"connectivity_{interface_id}"),
|
|
100
|
+
)
|
|
101
|
+
self._name_data: Final = get_hub_data_point_name_data(
|
|
102
|
+
channel=None, legacy_name=sensor_name, central_name=central_info.name
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
super().__init__(
|
|
106
|
+
unique_id=unique_id,
|
|
107
|
+
central_info=central_info,
|
|
108
|
+
event_bus_provider=event_bus_provider,
|
|
109
|
+
event_publisher=event_publisher,
|
|
110
|
+
task_scheduler=task_scheduler,
|
|
111
|
+
paramset_description_provider=paramset_description_provider,
|
|
112
|
+
parameter_visibility_provider=parameter_visibility_provider,
|
|
113
|
+
)
|
|
114
|
+
self._state_uncertain: bool = True
|
|
115
|
+
self._cached_value: bool = False
|
|
116
|
+
|
|
117
|
+
enabled_default: Final = DelegatedProperty[bool](path="_enabled_default")
|
|
118
|
+
full_name: Final = DelegatedProperty[str](path="_name_data.full_name")
|
|
119
|
+
name: Final = DelegatedProperty[str](path="_name_data.name", kind=Kind.CONFIG)
|
|
120
|
+
state_uncertain: Final = DelegatedProperty[bool](path="_state_uncertain")
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def available(self) -> bool:
|
|
124
|
+
"""
|
|
125
|
+
Return True - connectivity sensor is always available.
|
|
126
|
+
|
|
127
|
+
The sensor itself shows the connection state, so it should
|
|
128
|
+
never be marked unavailable.
|
|
129
|
+
"""
|
|
130
|
+
return True
|
|
131
|
+
|
|
132
|
+
@property
|
|
133
|
+
def channel(self) -> ChannelProtocol | None:
|
|
134
|
+
"""Return the identified channel."""
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def data_type(self) -> HubValueType | None:
|
|
139
|
+
"""Return the data type of the sensor."""
|
|
140
|
+
return HubValueType.LOGIC
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def description(self) -> str | None:
|
|
144
|
+
"""Return data point description."""
|
|
145
|
+
return f"Connectivity status for {self._interface.value} interface"
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def interface(self) -> Interface:
|
|
149
|
+
"""Return the interface type."""
|
|
150
|
+
return self._interface
|
|
151
|
+
|
|
152
|
+
@property
|
|
153
|
+
def interface_id(self) -> str:
|
|
154
|
+
"""Return the interface ID."""
|
|
155
|
+
return self._interface_id
|
|
156
|
+
|
|
157
|
+
@property
|
|
158
|
+
def legacy_name(self) -> str | None:
|
|
159
|
+
"""Return the original name."""
|
|
160
|
+
return None
|
|
161
|
+
|
|
162
|
+
@state_property
|
|
163
|
+
def value(self) -> bool:
|
|
164
|
+
"""Return True if interface is connected."""
|
|
165
|
+
return self._get_current_value()
|
|
166
|
+
|
|
167
|
+
def refresh(self, *, write_at: datetime) -> None:
|
|
168
|
+
"""Refresh the sensor value from health tracker."""
|
|
169
|
+
current_value = self._get_current_value()
|
|
170
|
+
if self._cached_value != current_value:
|
|
171
|
+
self._cached_value = current_value
|
|
172
|
+
self._set_modified_at(modified_at=write_at)
|
|
173
|
+
else:
|
|
174
|
+
self._set_refreshed_at(refreshed_at=write_at)
|
|
175
|
+
self._state_uncertain = False
|
|
176
|
+
self.publish_data_point_updated_event()
|
|
177
|
+
|
|
178
|
+
def _get_current_value(self) -> bool:
|
|
179
|
+
"""Return the current connectivity value."""
|
|
180
|
+
if (health := self._health_tracker.get_client_health(interface_id=self._interface_id)) is not None:
|
|
181
|
+
return health.is_available
|
|
182
|
+
return False
|
|
183
|
+
|
|
184
|
+
def _get_path_data(self) -> PathData:
|
|
185
|
+
"""Return the path data of the data_point."""
|
|
186
|
+
return HubPathData(name=slugify(f"connectivity_{self._interface.value}"))
|
|
187
|
+
|
|
188
|
+
def _get_signature(self) -> str:
|
|
189
|
+
"""Return the signature of the data_point."""
|
|
190
|
+
return f"{self._category}/{self.name}"
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# Copyright (c) 2021-2026
|
|
3
|
+
"""Module for AioHomematic hub data points."""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from datetime import datetime
|
|
8
|
+
from typing import Any, Final
|
|
9
|
+
|
|
10
|
+
from slugify import slugify
|
|
11
|
+
|
|
12
|
+
from aiohomematic.const import (
|
|
13
|
+
PROGRAM_ADDRESS,
|
|
14
|
+
SYSVAR_ADDRESS,
|
|
15
|
+
SYSVAR_TYPE,
|
|
16
|
+
HubData,
|
|
17
|
+
HubValueType,
|
|
18
|
+
ProgramData,
|
|
19
|
+
SystemVariableData,
|
|
20
|
+
)
|
|
21
|
+
from aiohomematic.decorators import inspector
|
|
22
|
+
from aiohomematic.interfaces import (
|
|
23
|
+
CentralInfoProtocol,
|
|
24
|
+
ChannelLookupProtocol,
|
|
25
|
+
ChannelProtocol,
|
|
26
|
+
ConfigProviderProtocol,
|
|
27
|
+
EventBusProviderProtocol,
|
|
28
|
+
EventPublisherProtocol,
|
|
29
|
+
GenericHubDataPointProtocol,
|
|
30
|
+
GenericProgramDataPointProtocol,
|
|
31
|
+
GenericSysvarDataPointProtocol,
|
|
32
|
+
HubDataFetcherProtocol,
|
|
33
|
+
ParameterVisibilityProviderProtocol,
|
|
34
|
+
ParamsetDescriptionProviderProtocol,
|
|
35
|
+
PrimaryClientProviderProtocol,
|
|
36
|
+
TaskSchedulerProtocol,
|
|
37
|
+
)
|
|
38
|
+
from aiohomematic.model.data_point import CallbackDataPoint
|
|
39
|
+
from aiohomematic.model.support import (
|
|
40
|
+
PathData,
|
|
41
|
+
ProgramPathData,
|
|
42
|
+
SysvarPathData,
|
|
43
|
+
generate_unique_id,
|
|
44
|
+
get_hub_data_point_name_data,
|
|
45
|
+
)
|
|
46
|
+
from aiohomematic.property_decorators import DelegatedProperty, Kind, state_property
|
|
47
|
+
from aiohomematic.support import PayloadMixin, parse_sys_var
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class GenericHubDataPoint(CallbackDataPoint, GenericHubDataPointProtocol, PayloadMixin):
|
|
51
|
+
"""Class for a Homematic system variable."""
|
|
52
|
+
|
|
53
|
+
__slots__ = (
|
|
54
|
+
"_channel",
|
|
55
|
+
"_description",
|
|
56
|
+
"_enabled_default",
|
|
57
|
+
"_legacy_name",
|
|
58
|
+
"_name_data",
|
|
59
|
+
"_primary_client_provider",
|
|
60
|
+
"_state_uncertain",
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
def __init__(
|
|
64
|
+
self,
|
|
65
|
+
*,
|
|
66
|
+
config_provider: ConfigProviderProtocol,
|
|
67
|
+
central_info: CentralInfoProtocol,
|
|
68
|
+
event_bus_provider: EventBusProviderProtocol,
|
|
69
|
+
event_publisher: EventPublisherProtocol,
|
|
70
|
+
task_scheduler: TaskSchedulerProtocol,
|
|
71
|
+
paramset_description_provider: ParamsetDescriptionProviderProtocol,
|
|
72
|
+
parameter_visibility_provider: ParameterVisibilityProviderProtocol,
|
|
73
|
+
channel_lookup: ChannelLookupProtocol,
|
|
74
|
+
primary_client_provider: PrimaryClientProviderProtocol,
|
|
75
|
+
address: str,
|
|
76
|
+
data: HubData,
|
|
77
|
+
) -> None:
|
|
78
|
+
"""Initialize the data_point."""
|
|
79
|
+
PayloadMixin.__init__(self)
|
|
80
|
+
unique_id: Final = generate_unique_id(
|
|
81
|
+
config_provider=config_provider,
|
|
82
|
+
address=address,
|
|
83
|
+
parameter=slugify(data.legacy_name),
|
|
84
|
+
)
|
|
85
|
+
self._legacy_name = data.legacy_name
|
|
86
|
+
self._channel = channel_lookup.identify_channel(text=data.legacy_name)
|
|
87
|
+
self._name_data: Final = get_hub_data_point_name_data(
|
|
88
|
+
channel=self._channel, legacy_name=data.legacy_name, central_name=central_info.name
|
|
89
|
+
)
|
|
90
|
+
self._description = data.description
|
|
91
|
+
super().__init__(
|
|
92
|
+
unique_id=unique_id,
|
|
93
|
+
central_info=central_info,
|
|
94
|
+
event_bus_provider=event_bus_provider,
|
|
95
|
+
event_publisher=event_publisher,
|
|
96
|
+
task_scheduler=task_scheduler,
|
|
97
|
+
paramset_description_provider=paramset_description_provider,
|
|
98
|
+
parameter_visibility_provider=parameter_visibility_provider,
|
|
99
|
+
)
|
|
100
|
+
self._enabled_default: Final = data.enabled_default
|
|
101
|
+
self._state_uncertain: bool = True
|
|
102
|
+
self._primary_client_provider: Final = primary_client_provider
|
|
103
|
+
|
|
104
|
+
channel: Final = DelegatedProperty[ChannelProtocol | None](path="_channel")
|
|
105
|
+
description: Final = DelegatedProperty[str | None](path="_description", kind=Kind.CONFIG)
|
|
106
|
+
enabled_default: Final = DelegatedProperty[bool](path="_enabled_default")
|
|
107
|
+
full_name: Final = DelegatedProperty[str](path="_name_data.full_name")
|
|
108
|
+
legacy_name: Final = DelegatedProperty[str | None](path="_legacy_name")
|
|
109
|
+
name: Final = DelegatedProperty[str](path="_name_data.name", kind=Kind.CONFIG)
|
|
110
|
+
state_uncertain: Final = DelegatedProperty[bool](path="_state_uncertain")
|
|
111
|
+
|
|
112
|
+
@state_property
|
|
113
|
+
def available(self) -> bool:
|
|
114
|
+
"""Return the availability of the device."""
|
|
115
|
+
return self._central_info.available
|
|
116
|
+
|
|
117
|
+
def _get_signature(self) -> str:
|
|
118
|
+
"""Return the signature of the data_point."""
|
|
119
|
+
return f"{self._category}/{self.name}"
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
class GenericSysvarDataPoint(GenericHubDataPoint, GenericSysvarDataPointProtocol):
|
|
123
|
+
"""Class for a Homematic system variable."""
|
|
124
|
+
|
|
125
|
+
__slots__ = (
|
|
126
|
+
"_current_value",
|
|
127
|
+
"_data_type",
|
|
128
|
+
"_max",
|
|
129
|
+
"_min",
|
|
130
|
+
"_previous_value",
|
|
131
|
+
"_temporary_value",
|
|
132
|
+
"_unit",
|
|
133
|
+
"_values",
|
|
134
|
+
"_vid",
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
_is_extended = False
|
|
138
|
+
|
|
139
|
+
def __init__(
|
|
140
|
+
self,
|
|
141
|
+
*,
|
|
142
|
+
config_provider: ConfigProviderProtocol,
|
|
143
|
+
central_info: CentralInfoProtocol,
|
|
144
|
+
event_bus_provider: EventBusProviderProtocol,
|
|
145
|
+
event_publisher: EventPublisherProtocol,
|
|
146
|
+
task_scheduler: TaskSchedulerProtocol,
|
|
147
|
+
paramset_description_provider: ParamsetDescriptionProviderProtocol,
|
|
148
|
+
parameter_visibility_provider: ParameterVisibilityProviderProtocol,
|
|
149
|
+
channel_lookup: ChannelLookupProtocol,
|
|
150
|
+
primary_client_provider: PrimaryClientProviderProtocol,
|
|
151
|
+
data: SystemVariableData,
|
|
152
|
+
) -> None:
|
|
153
|
+
"""Initialize the data_point."""
|
|
154
|
+
self._vid: Final = data.vid
|
|
155
|
+
super().__init__(
|
|
156
|
+
config_provider=config_provider,
|
|
157
|
+
central_info=central_info,
|
|
158
|
+
event_bus_provider=event_bus_provider,
|
|
159
|
+
event_publisher=event_publisher,
|
|
160
|
+
task_scheduler=task_scheduler,
|
|
161
|
+
paramset_description_provider=paramset_description_provider,
|
|
162
|
+
parameter_visibility_provider=parameter_visibility_provider,
|
|
163
|
+
channel_lookup=channel_lookup,
|
|
164
|
+
primary_client_provider=primary_client_provider,
|
|
165
|
+
address=SYSVAR_ADDRESS,
|
|
166
|
+
data=data,
|
|
167
|
+
)
|
|
168
|
+
self._data_type = data.data_type
|
|
169
|
+
self._values: Final[tuple[str, ...] | None] = tuple(data.values) if data.values else None
|
|
170
|
+
self._max: Final = data.max_value
|
|
171
|
+
self._min: Final = data.min_value
|
|
172
|
+
self._unit: Final = data.unit
|
|
173
|
+
self._current_value: SYSVAR_TYPE = data.value
|
|
174
|
+
self._previous_value: SYSVAR_TYPE = None
|
|
175
|
+
self._temporary_value: SYSVAR_TYPE = None
|
|
176
|
+
|
|
177
|
+
is_extended: Final = DelegatedProperty[bool](path="_is_extended")
|
|
178
|
+
max: Final = DelegatedProperty[float | int | None](path="_max", kind=Kind.CONFIG)
|
|
179
|
+
min: Final = DelegatedProperty[float | int | None](path="_min", kind=Kind.CONFIG)
|
|
180
|
+
previous_value: Final = DelegatedProperty[SYSVAR_TYPE](path="_previous_value")
|
|
181
|
+
unit: Final = DelegatedProperty[str | None](path="_unit", kind=Kind.CONFIG)
|
|
182
|
+
values: Final = DelegatedProperty[tuple[str, ...] | None](path="_values", kind=Kind.STATE)
|
|
183
|
+
vid: Final = DelegatedProperty[str](path="_vid", kind=Kind.CONFIG)
|
|
184
|
+
|
|
185
|
+
@property
|
|
186
|
+
def _value(self) -> Any | None:
|
|
187
|
+
"""Return the value."""
|
|
188
|
+
return self._temporary_value if self._temporary_refreshed_at > self._refreshed_at else self._current_value
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
def data_type(self) -> HubValueType | None:
|
|
192
|
+
"""Return the data type."""
|
|
193
|
+
return self._data_type
|
|
194
|
+
|
|
195
|
+
@data_type.setter
|
|
196
|
+
def data_type(self, data_type: HubValueType) -> None:
|
|
197
|
+
"""Write data_type."""
|
|
198
|
+
self._data_type = data_type
|
|
199
|
+
|
|
200
|
+
@state_property
|
|
201
|
+
def value(self) -> Any | None:
|
|
202
|
+
"""Return the value."""
|
|
203
|
+
return self._value
|
|
204
|
+
|
|
205
|
+
async def event(self, *, value: Any, received_at: datetime) -> None:
|
|
206
|
+
"""Handle event for which this data_point has subscribed."""
|
|
207
|
+
self.write_value(value=value, write_at=received_at)
|
|
208
|
+
|
|
209
|
+
@inspector
|
|
210
|
+
async def send_variable(self, *, value: Any) -> None:
|
|
211
|
+
"""Set variable value on the backend."""
|
|
212
|
+
if client := self._primary_client_provider.primary_client:
|
|
213
|
+
await client.set_system_variable(
|
|
214
|
+
legacy_name=self._legacy_name, value=parse_sys_var(data_type=self._data_type, raw_value=value)
|
|
215
|
+
)
|
|
216
|
+
self._write_temporary_value(value=value, write_at=datetime.now())
|
|
217
|
+
|
|
218
|
+
def write_value(self, *, value: Any, write_at: datetime) -> None:
|
|
219
|
+
"""Set variable value on the backend."""
|
|
220
|
+
self._reset_temporary_value()
|
|
221
|
+
|
|
222
|
+
old_value = self._current_value
|
|
223
|
+
new_value = self._convert_value(old_value=old_value, new_value=value)
|
|
224
|
+
if old_value == new_value:
|
|
225
|
+
self._set_refreshed_at(refreshed_at=write_at)
|
|
226
|
+
else:
|
|
227
|
+
self._set_modified_at(modified_at=write_at)
|
|
228
|
+
self._previous_value = old_value
|
|
229
|
+
self._current_value = new_value
|
|
230
|
+
self._state_uncertain = False
|
|
231
|
+
self.publish_data_point_updated_event()
|
|
232
|
+
|
|
233
|
+
def _convert_value(self, *, old_value: Any, new_value: Any) -> Any:
|
|
234
|
+
"""Convert to value to SYSVAR_TYPE."""
|
|
235
|
+
if new_value is None:
|
|
236
|
+
return None
|
|
237
|
+
value = new_value
|
|
238
|
+
if self._data_type:
|
|
239
|
+
value = parse_sys_var(data_type=self._data_type, raw_value=new_value)
|
|
240
|
+
elif isinstance(old_value, bool):
|
|
241
|
+
value = bool(new_value)
|
|
242
|
+
elif isinstance(old_value, int):
|
|
243
|
+
value = int(new_value)
|
|
244
|
+
elif isinstance(old_value, str):
|
|
245
|
+
value = str(new_value)
|
|
246
|
+
elif isinstance(old_value, float):
|
|
247
|
+
value = float(new_value)
|
|
248
|
+
return value
|
|
249
|
+
|
|
250
|
+
def _get_path_data(self) -> PathData:
|
|
251
|
+
"""Return the path data of the data_point."""
|
|
252
|
+
return SysvarPathData(vid=self._vid)
|
|
253
|
+
|
|
254
|
+
def _reset_temporary_value(self) -> None:
|
|
255
|
+
"""Reset the temp storage."""
|
|
256
|
+
self._temporary_value = None
|
|
257
|
+
self._reset_temporary_timestamps()
|
|
258
|
+
|
|
259
|
+
def _write_temporary_value(self, *, value: Any, write_at: datetime) -> None:
|
|
260
|
+
"""Update the temporary value of the data_point."""
|
|
261
|
+
self._reset_temporary_value()
|
|
262
|
+
|
|
263
|
+
temp_value = self._convert_value(old_value=self._current_value, new_value=value)
|
|
264
|
+
if self._value == temp_value:
|
|
265
|
+
self._set_temporary_refreshed_at(refreshed_at=write_at)
|
|
266
|
+
else:
|
|
267
|
+
self._set_temporary_modified_at(modified_at=write_at)
|
|
268
|
+
self._temporary_value = temp_value
|
|
269
|
+
self._state_uncertain = True
|
|
270
|
+
self.publish_data_point_updated_event()
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
class GenericProgramDataPoint(GenericHubDataPoint, GenericProgramDataPointProtocol):
|
|
274
|
+
"""Class for a generic Homematic progran data point."""
|
|
275
|
+
|
|
276
|
+
__slots__ = (
|
|
277
|
+
"_hub_data_fetcher",
|
|
278
|
+
"_is_active",
|
|
279
|
+
"_is_internal",
|
|
280
|
+
"_last_execute_time",
|
|
281
|
+
"_pid",
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
def __init__(
|
|
285
|
+
self,
|
|
286
|
+
*,
|
|
287
|
+
config_provider: ConfigProviderProtocol,
|
|
288
|
+
central_info: CentralInfoProtocol,
|
|
289
|
+
event_bus_provider: EventBusProviderProtocol,
|
|
290
|
+
event_publisher: EventPublisherProtocol,
|
|
291
|
+
task_scheduler: TaskSchedulerProtocol,
|
|
292
|
+
paramset_description_provider: ParamsetDescriptionProviderProtocol,
|
|
293
|
+
parameter_visibility_provider: ParameterVisibilityProviderProtocol,
|
|
294
|
+
channel_lookup: ChannelLookupProtocol,
|
|
295
|
+
primary_client_provider: PrimaryClientProviderProtocol,
|
|
296
|
+
hub_data_fetcher: HubDataFetcherProtocol,
|
|
297
|
+
data: ProgramData,
|
|
298
|
+
) -> None:
|
|
299
|
+
"""Initialize the data_point."""
|
|
300
|
+
self._pid: Final = data.pid
|
|
301
|
+
super().__init__(
|
|
302
|
+
config_provider=config_provider,
|
|
303
|
+
central_info=central_info,
|
|
304
|
+
event_bus_provider=event_bus_provider,
|
|
305
|
+
event_publisher=event_publisher,
|
|
306
|
+
task_scheduler=task_scheduler,
|
|
307
|
+
paramset_description_provider=paramset_description_provider,
|
|
308
|
+
parameter_visibility_provider=parameter_visibility_provider,
|
|
309
|
+
channel_lookup=channel_lookup,
|
|
310
|
+
primary_client_provider=primary_client_provider,
|
|
311
|
+
address=PROGRAM_ADDRESS,
|
|
312
|
+
data=data,
|
|
313
|
+
)
|
|
314
|
+
self._is_active: bool = data.is_active
|
|
315
|
+
self._is_internal: bool = data.is_internal
|
|
316
|
+
self._last_execute_time: str = data.last_execute_time
|
|
317
|
+
self._state_uncertain: bool = True
|
|
318
|
+
self._hub_data_fetcher: Final = hub_data_fetcher
|
|
319
|
+
|
|
320
|
+
is_active: Final = DelegatedProperty[bool](path="_is_active", kind=Kind.STATE)
|
|
321
|
+
is_internal: Final = DelegatedProperty[bool](path="_is_internal", kind=Kind.CONFIG)
|
|
322
|
+
last_execute_time: Final = DelegatedProperty[str](path="_last_execute_time", kind=Kind.STATE)
|
|
323
|
+
pid: Final = DelegatedProperty[str](path="_pid", kind=Kind.CONFIG)
|
|
324
|
+
|
|
325
|
+
def update_data(self, *, data: ProgramData) -> None:
|
|
326
|
+
"""Set variable value on the backend."""
|
|
327
|
+
do_update: bool = False
|
|
328
|
+
if self._is_active != data.is_active:
|
|
329
|
+
self._is_active = data.is_active
|
|
330
|
+
do_update = True
|
|
331
|
+
if self._is_internal != data.is_internal:
|
|
332
|
+
self._is_internal = data.is_internal
|
|
333
|
+
do_update = True
|
|
334
|
+
if self._last_execute_time != data.last_execute_time:
|
|
335
|
+
self._last_execute_time = data.last_execute_time
|
|
336
|
+
do_update = True
|
|
337
|
+
if do_update:
|
|
338
|
+
self.publish_data_point_updated_event()
|
|
339
|
+
|
|
340
|
+
def _get_path_data(self) -> PathData:
|
|
341
|
+
"""Return the path data of the data_point."""
|
|
342
|
+
return ProgramPathData(pid=self.pid)
|