pyvlx 0.2.27__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.
Files changed (84) hide show
  1. pyvlx/__init__.py +21 -0
  2. pyvlx/api/__init__.py +23 -0
  3. pyvlx/api/activate_scene.py +63 -0
  4. pyvlx/api/api_event.py +73 -0
  5. pyvlx/api/command_send.py +85 -0
  6. pyvlx/api/factory_default.py +34 -0
  7. pyvlx/api/frame_creation.py +202 -0
  8. pyvlx/api/frames/__init__.py +76 -0
  9. pyvlx/api/frames/alias_array.py +45 -0
  10. pyvlx/api/frames/frame.py +56 -0
  11. pyvlx/api/frames/frame_activate_scene.py +92 -0
  12. pyvlx/api/frames/frame_activation_log_updated.py +14 -0
  13. pyvlx/api/frames/frame_command_send.py +280 -0
  14. pyvlx/api/frames/frame_discover_nodes.py +64 -0
  15. pyvlx/api/frames/frame_error_notification.py +42 -0
  16. pyvlx/api/frames/frame_facory_default.py +32 -0
  17. pyvlx/api/frames/frame_get_all_nodes_information.py +218 -0
  18. pyvlx/api/frames/frame_get_limitation.py +127 -0
  19. pyvlx/api/frames/frame_get_local_time.py +38 -0
  20. pyvlx/api/frames/frame_get_network_setup.py +64 -0
  21. pyvlx/api/frames/frame_get_node_information.py +223 -0
  22. pyvlx/api/frames/frame_get_protocol_version.py +53 -0
  23. pyvlx/api/frames/frame_get_scene_list.py +82 -0
  24. pyvlx/api/frames/frame_get_state.py +47 -0
  25. pyvlx/api/frames/frame_get_version.py +72 -0
  26. pyvlx/api/frames/frame_helper.py +40 -0
  27. pyvlx/api/frames/frame_house_status_monitor_disable_cfm.py +14 -0
  28. pyvlx/api/frames/frame_house_status_monitor_disable_req.py +14 -0
  29. pyvlx/api/frames/frame_house_status_monitor_enable_cfm.py +14 -0
  30. pyvlx/api/frames/frame_house_status_monitor_enable_req.py +14 -0
  31. pyvlx/api/frames/frame_leave_learn_state.py +41 -0
  32. pyvlx/api/frames/frame_node_information_changed.py +57 -0
  33. pyvlx/api/frames/frame_node_state_position_changed_notification.py +84 -0
  34. pyvlx/api/frames/frame_password_change.py +114 -0
  35. pyvlx/api/frames/frame_password_enter.py +70 -0
  36. pyvlx/api/frames/frame_reboot.py +32 -0
  37. pyvlx/api/frames/frame_set_node_name.py +73 -0
  38. pyvlx/api/frames/frame_set_utc.py +45 -0
  39. pyvlx/api/frames/frame_status_request.py +212 -0
  40. pyvlx/api/get_all_nodes_information.py +46 -0
  41. pyvlx/api/get_limitation.py +64 -0
  42. pyvlx/api/get_local_time.py +34 -0
  43. pyvlx/api/get_network_setup.py +34 -0
  44. pyvlx/api/get_node_information.py +42 -0
  45. pyvlx/api/get_protocol_version.py +40 -0
  46. pyvlx/api/get_scene_list.py +49 -0
  47. pyvlx/api/get_state.py +43 -0
  48. pyvlx/api/get_version.py +34 -0
  49. pyvlx/api/house_status_monitor.py +52 -0
  50. pyvlx/api/leave_learn_state.py +33 -0
  51. pyvlx/api/password_enter.py +39 -0
  52. pyvlx/api/reboot.py +33 -0
  53. pyvlx/api/session_id.py +20 -0
  54. pyvlx/api/set_node_name.py +32 -0
  55. pyvlx/api/set_utc.py +31 -0
  56. pyvlx/api/status_request.py +48 -0
  57. pyvlx/config.py +54 -0
  58. pyvlx/connection.py +182 -0
  59. pyvlx/const.py +685 -0
  60. pyvlx/dataobjects.py +161 -0
  61. pyvlx/discovery.py +100 -0
  62. pyvlx/exception.py +26 -0
  63. pyvlx/heartbeat.py +79 -0
  64. pyvlx/klf200gateway.py +167 -0
  65. pyvlx/lightening_device.py +102 -0
  66. pyvlx/log.py +4 -0
  67. pyvlx/node.py +74 -0
  68. pyvlx/node_helper.py +165 -0
  69. pyvlx/node_updater.py +162 -0
  70. pyvlx/nodes.py +99 -0
  71. pyvlx/on_off_switch.py +44 -0
  72. pyvlx/opening_device.py +644 -0
  73. pyvlx/parameter.py +357 -0
  74. pyvlx/py.typed +0 -0
  75. pyvlx/pyvlx.py +124 -0
  76. pyvlx/scene.py +53 -0
  77. pyvlx/scenes.py +60 -0
  78. pyvlx/slip.py +48 -0
  79. pyvlx/string_helper.py +20 -0
  80. pyvlx-0.2.27.dist-info/METADATA +122 -0
  81. pyvlx-0.2.27.dist-info/RECORD +84 -0
  82. pyvlx-0.2.27.dist-info/WHEEL +5 -0
  83. pyvlx-0.2.27.dist-info/licenses/LICENSE +165 -0
  84. pyvlx-0.2.27.dist-info/top_level.txt +1 -0
pyvlx/__init__.py ADDED
@@ -0,0 +1,21 @@
1
+ """Module for accessing KLF 200 gateway with python."""
2
+
3
+ from .discovery import VeluxDiscovery
4
+ from .exception import PyVLXException
5
+ from .klf200gateway import Klf200Gateway
6
+ from .lightening_device import Light, LighteningDevice
7
+ from .log import PYVLXLOG
8
+ from .node import Node
9
+ from .nodes import Nodes
10
+ from .on_off_switch import OnOffSwitch
11
+ from .opening_device import (
12
+ Awning, Blade, Blind, GarageDoor, Gate, OpeningDevice, RollerShutter,
13
+ Window)
14
+ from .parameter import (
15
+ CurrentIntensity, CurrentPosition, Intensity, Parameter, Position,
16
+ SwitchParameter, SwitchParameterOff, SwitchParameterOn, UnknownIntensity,
17
+ UnknownPosition)
18
+ # flake8: noqa
19
+ from .pyvlx import PyVLX
20
+ from .scene import Scene
21
+ from .scenes import Scenes
pyvlx/api/__init__.py ADDED
@@ -0,0 +1,23 @@
1
+ """Module for all KLF 200 API frames."""
2
+ # flake8: noqa
3
+
4
+ from .activate_scene import ActivateScene
5
+ from .api_event import ApiEvent
6
+ from .command_send import CommandSend
7
+ from .factory_default import FactoryDefault
8
+ from .get_all_nodes_information import GetAllNodesInformation
9
+ from .get_local_time import (
10
+ FrameGetLocalTimeConfirmation, FrameGetLocalTimeRequest, GetLocalTime)
11
+ from .get_network_setup import GetNetworkSetup
12
+ from .get_node_information import GetNodeInformation
13
+ from .get_protocol_version import GetProtocolVersion
14
+ from .get_scene_list import GetSceneList
15
+ from .get_state import GetState
16
+ from .get_version import GetVersion
17
+ from .house_status_monitor import (
18
+ HouseStatusMonitorDisable, HouseStatusMonitorEnable)
19
+ from .leave_learn_state import LeaveLearnState
20
+ from .password_enter import PasswordEnter
21
+ from .reboot import Reboot
22
+ from .set_node_name import SetNodeName
23
+ from .set_utc import SetUTC
@@ -0,0 +1,63 @@
1
+ """Module for retrieving scene list from API."""
2
+ from typing import TYPE_CHECKING, Optional
3
+
4
+ from .api_event import ApiEvent
5
+ from .frames import (
6
+ ActivateSceneConfirmationStatus, FrameActivateSceneConfirmation,
7
+ FrameActivateSceneRequest, FrameBase,
8
+ FrameCommandRemainingTimeNotification, FrameCommandRunStatusNotification,
9
+ FrameSessionFinishedNotification)
10
+ from .session_id import get_new_session_id
11
+
12
+ if TYPE_CHECKING:
13
+ from pyvlx import PyVLX
14
+
15
+
16
+ class ActivateScene(ApiEvent):
17
+ """Class for activating scene via API."""
18
+
19
+ def __init__(
20
+ self, pyvlx: "PyVLX", scene_id: int, wait_for_completion: bool = True, timeout_in_seconds: int = 60
21
+ ):
22
+ """Initialize SceneList class."""
23
+ super().__init__(pyvlx=pyvlx, timeout_in_seconds=timeout_in_seconds)
24
+ self.success = False
25
+ self.scene_id = scene_id
26
+ self.wait_for_completion = wait_for_completion
27
+ self.session_id: Optional[int] = None
28
+
29
+ async def handle_frame(self, frame: FrameBase) -> bool:
30
+ """Handle incoming API frame, return True if this was the expected frame."""
31
+ if (
32
+ isinstance(frame, FrameActivateSceneConfirmation)
33
+ and frame.session_id == self.session_id
34
+ ):
35
+ if frame.status == ActivateSceneConfirmationStatus.ACCEPTED:
36
+ self.success = True
37
+ return not self.wait_for_completion
38
+ if (
39
+ isinstance(frame, FrameCommandRemainingTimeNotification)
40
+ and frame.session_id == self.session_id
41
+ ):
42
+ # Ignoring FrameCommandRemainingTimeNotification
43
+ return False
44
+ if (
45
+ isinstance(frame, FrameCommandRunStatusNotification)
46
+ and frame.session_id == self.session_id
47
+ ):
48
+ # At the moment I don't reall understand what the FrameCommandRunStatusNotification is good for.
49
+ # Ignoring these packets for now
50
+ return False
51
+ if (
52
+ isinstance(frame, FrameSessionFinishedNotification)
53
+ and frame.session_id == self.session_id
54
+ ):
55
+ return True
56
+ return False
57
+
58
+ def request_frame(self) -> FrameActivateSceneRequest:
59
+ """Construct initiating frame."""
60
+ self.session_id = get_new_session_id()
61
+ return FrameActivateSceneRequest(
62
+ scene_id=self.scene_id, session_id=self.session_id
63
+ )
pyvlx/api/api_event.py ADDED
@@ -0,0 +1,73 @@
1
+ """Base class for waiting for a specific answer frame from velux ap.."""
2
+ import asyncio
3
+ from typing import TYPE_CHECKING, Optional
4
+
5
+ from .frames import FrameBase
6
+
7
+ if TYPE_CHECKING:
8
+ from pyvlx import PyVLX
9
+
10
+
11
+ class ApiEvent:
12
+ """Base class for waiting a specific frame from API connection."""
13
+
14
+ def __init__(self, pyvlx: "PyVLX", timeout_in_seconds: int = 10):
15
+ """Initialize ApiEvent."""
16
+ self.pyvlx = pyvlx
17
+ self.response_received_or_timeout = asyncio.Event()
18
+
19
+ self.success = False
20
+ self.timeout_in_seconds = timeout_in_seconds
21
+ self.timeout_callback = None
22
+ self.timeout_handle: Optional[asyncio.TimerHandle] = None
23
+
24
+ async def do_api_call(self) -> None:
25
+ """Start. Sending and waiting for answer."""
26
+ # We check for connection before entering the semaphore section
27
+ # because otherwise we might try to connect, which calls this, and we get stuck on
28
+ # the semaphore.
29
+ await self.pyvlx.check_connected()
30
+
31
+ if self.pyvlx.get_connected():
32
+ async with self.pyvlx.api_call_semaphore:
33
+ self.pyvlx.connection.register_frame_received_cb(self.response_rec_callback)
34
+ await self.send_frame()
35
+ await self.start_timeout()
36
+ await self.response_received_or_timeout.wait()
37
+ self.response_received_or_timeout.clear()
38
+ await self.stop_timeout()
39
+ self.pyvlx.connection.unregister_frame_received_cb(self.response_rec_callback)
40
+ else:
41
+ self.success = False
42
+
43
+ async def handle_frame(self, frame: FrameBase) -> bool:
44
+ """Handle incoming API frame, return True if this was the expected frame."""
45
+ raise NotImplementedError("handle_frame has to be implemented")
46
+
47
+ async def send_frame(self) -> None:
48
+ """Send frame to API connection."""
49
+ await self.pyvlx.send_frame(self.request_frame())
50
+
51
+ def request_frame(self) -> FrameBase:
52
+ """Construct initiating frame."""
53
+ raise NotImplementedError("send_frame has to be implemented")
54
+
55
+ async def response_rec_callback(self, frame: FrameBase) -> None:
56
+ """Handle frame. Callback from internal api connection."""
57
+ if await self.handle_frame(frame):
58
+ self.response_received_or_timeout.set()
59
+
60
+ def timeout(self) -> None:
61
+ """Handle timeout for not having received expected frame."""
62
+ self.response_received_or_timeout.set()
63
+
64
+ async def start_timeout(self) -> None:
65
+ """Start timeout."""
66
+ self.timeout_handle = self.pyvlx.connection.loop.call_later(
67
+ self.timeout_in_seconds, self.timeout
68
+ )
69
+
70
+ async def stop_timeout(self) -> None:
71
+ """Stop timeout."""
72
+ if self.timeout_handle is not None:
73
+ self.timeout_handle.cancel()
@@ -0,0 +1,85 @@
1
+ """Module for retrieving scene list from API."""
2
+ from typing import TYPE_CHECKING, Any, Optional
3
+
4
+ from ..exception import PyVLXException
5
+ from ..parameter import Parameter
6
+ from .api_event import ApiEvent
7
+ from .frames import (
8
+ CommandSendConfirmationStatus, FrameBase,
9
+ FrameCommandRemainingTimeNotification, FrameCommandRunStatusNotification,
10
+ FrameCommandSendConfirmation, FrameCommandSendRequest,
11
+ FrameSessionFinishedNotification)
12
+ from .session_id import get_new_session_id
13
+
14
+ if TYPE_CHECKING:
15
+ from pyvlx import PyVLX
16
+
17
+
18
+ class CommandSend(ApiEvent):
19
+ """Class for sending command to API."""
20
+
21
+ def __init__(
22
+ self,
23
+ pyvlx: "PyVLX",
24
+ node_id: int,
25
+ parameter: Parameter,
26
+ active_parameter: int = 0,
27
+ wait_for_completion: bool = True,
28
+ timeout_in_seconds: int = 2,
29
+ **functional_parameter: Any
30
+ ):
31
+ """Initialize SceneList class."""
32
+ super().__init__(pyvlx=pyvlx, timeout_in_seconds=timeout_in_seconds)
33
+ self.success = False
34
+ self.node_id = node_id
35
+ self.parameter = parameter
36
+ self.active_parameter = active_parameter
37
+ self.functional_parameter = functional_parameter
38
+ self.wait_for_completion = wait_for_completion
39
+ self.session_id: Optional[int] = None
40
+
41
+ async def handle_frame(self, frame: FrameBase) -> bool:
42
+ """Handle incoming API frame, return True if this was the expected frame."""
43
+ if (
44
+ isinstance(frame, FrameCommandSendConfirmation)
45
+ and frame.session_id == self.session_id
46
+ ):
47
+ if frame.status == CommandSendConfirmationStatus.ACCEPTED:
48
+ self.success = True
49
+ return not self.wait_for_completion
50
+ if (
51
+ isinstance(frame, FrameCommandRemainingTimeNotification)
52
+ and frame.session_id == self.session_id
53
+ ):
54
+ # Ignoring FrameCommandRemainingTimeNotification
55
+ return False
56
+ if (
57
+ isinstance(frame, FrameCommandRunStatusNotification)
58
+ and frame.session_id == self.session_id
59
+ ):
60
+ # At the moment I don't reall understand what the FrameCommandRunStatusNotification is good for.
61
+ # Ignoring these packets for now
62
+ return False
63
+ if (
64
+ isinstance(frame, FrameSessionFinishedNotification)
65
+ and frame.session_id == self.session_id
66
+ ):
67
+ return True
68
+ return False
69
+
70
+ async def send(self) -> None:
71
+ """Send frame to KLF200."""
72
+ await self.do_api_call()
73
+ if not self.success:
74
+ raise PyVLXException("Unable to send command")
75
+
76
+ def request_frame(self) -> FrameCommandSendRequest:
77
+ """Construct initiating frame."""
78
+ self.session_id = get_new_session_id()
79
+ return FrameCommandSendRequest(
80
+ node_ids=[self.node_id],
81
+ parameter=self.parameter,
82
+ active_parameter=self.active_parameter,
83
+ session_id=self.session_id,
84
+ **self.functional_parameter
85
+ )
@@ -0,0 +1,34 @@
1
+ """Module for handling the FactoryDefault to API."""
2
+ from typing import TYPE_CHECKING
3
+
4
+ from pyvlx.log import PYVLXLOG
5
+
6
+ from .api_event import ApiEvent
7
+ from .frames import (
8
+ FrameBase, FrameGatewayFactoryDefaultConfirmation,
9
+ FrameGatewayFactoryDefaultRequest)
10
+
11
+ if TYPE_CHECKING:
12
+ from pyvlx import PyVLX
13
+
14
+
15
+ class FactoryDefault(ApiEvent):
16
+ """Class for handling Factory reset API."""
17
+
18
+ def __init__(self, pyvlx: "PyVLX"):
19
+ """Initialize facotry default class."""
20
+ super().__init__(pyvlx=pyvlx)
21
+ self.pyvlx = pyvlx
22
+ self.success = False
23
+
24
+ async def handle_frame(self, frame: FrameBase) -> bool:
25
+ """Handle incoming API frame, return True if this was the expected frame."""
26
+ if isinstance(frame, FrameGatewayFactoryDefaultConfirmation):
27
+ PYVLXLOG.warning("KLF200 is factory resetting")
28
+ self.success = True
29
+ return True
30
+ return False
31
+
32
+ def request_frame(self) -> FrameGatewayFactoryDefaultRequest:
33
+ """Construct initiating frame."""
34
+ return FrameGatewayFactoryDefaultRequest()
@@ -0,0 +1,202 @@
1
+ """Helper module for creating a frame out of raw data."""
2
+ from typing import Optional
3
+
4
+ from pyvlx.const import Command
5
+ from pyvlx.log import PYVLXLOG
6
+
7
+ from .frames import (
8
+ FrameActivateSceneConfirmation, FrameActivateSceneRequest,
9
+ FrameActivationLogUpdatedNotification, FrameBase,
10
+ FrameCommandRemainingTimeNotification, FrameCommandRunStatusNotification,
11
+ FrameCommandSendConfirmation, FrameCommandSendRequest,
12
+ FrameDiscoverNodesConfirmation, FrameDiscoverNodesNotification,
13
+ FrameDiscoverNodesRequest, FrameErrorNotification,
14
+ FrameGatewayFactoryDefaultConfirmation, FrameGatewayFactoryDefaultRequest,
15
+ FrameGatewayRebootConfirmation, FrameGatewayRebootRequest,
16
+ FrameGetAllNodesInformationConfirmation,
17
+ FrameGetAllNodesInformationFinishedNotification,
18
+ FrameGetAllNodesInformationNotification,
19
+ FrameGetAllNodesInformationRequest, FrameGetLimitationStatus,
20
+ FrameGetLimitationStatusConfirmation, FrameGetLimitationStatusNotification,
21
+ FrameGetLocalTimeConfirmation, FrameGetLocalTimeRequest,
22
+ FrameGetNetworkSetupConfirmation, FrameGetNetworkSetupRequest,
23
+ FrameGetNodeInformationConfirmation, FrameGetNodeInformationNotification,
24
+ FrameGetNodeInformationRequest, FrameGetProtocolVersionConfirmation,
25
+ FrameGetProtocolVersionRequest, FrameGetSceneListConfirmation,
26
+ FrameGetSceneListNotification, FrameGetSceneListRequest,
27
+ FrameGetStateConfirmation, FrameGetStateRequest,
28
+ FrameGetVersionConfirmation, FrameGetVersionRequest,
29
+ FrameHouseStatusMonitorDisableConfirmation,
30
+ FrameHouseStatusMonitorDisableRequest,
31
+ FrameHouseStatusMonitorEnableConfirmation,
32
+ FrameHouseStatusMonitorEnableRequest, FrameLeaveLearnStateConfirmation,
33
+ FrameLeaveLearnStateRequest, FrameNodeInformationChangedNotification,
34
+ FrameNodeStatePositionChangedNotification, FramePasswordChangeConfirmation,
35
+ FramePasswordChangeNotification, FramePasswordChangeRequest,
36
+ FramePasswordEnterConfirmation, FramePasswordEnterRequest,
37
+ FrameSessionFinishedNotification, FrameSetNodeNameConfirmation,
38
+ FrameSetNodeNameRequest, FrameSetUTCConfirmation, FrameSetUTCRequest,
39
+ FrameStatusRequestConfirmation, FrameStatusRequestNotification,
40
+ FrameStatusRequestRequest, extract_from_frame)
41
+
42
+
43
+ def frame_from_raw(raw: bytes) -> Optional[FrameBase]:
44
+ """Create and return frame from raw bytes."""
45
+ command, payload = extract_from_frame(raw)
46
+ frame = create_frame(command)
47
+ if frame is None:
48
+ PYVLXLOG.warning(
49
+ "Command %s not implemented, raw: %s",
50
+ command,
51
+ ":".join("{:02x}".format(c) for c in raw),
52
+ )
53
+ return None
54
+ frame.validate_payload_len(payload)
55
+ frame.from_payload(payload)
56
+ return frame
57
+
58
+
59
+ def create_frame(command: Command) -> Optional[FrameBase]:
60
+ """Create and return empty Frame from Command."""
61
+ # pylint: disable=too-many-branches,too-many-return-statements,too-many-statements
62
+ if command == Command.GW_ERROR_NTF:
63
+ return FrameErrorNotification()
64
+ if command == Command.GW_COMMAND_SEND_REQ:
65
+ return FrameCommandSendRequest()
66
+ if command == Command.GW_COMMAND_SEND_CFM:
67
+ return FrameCommandSendConfirmation()
68
+ if command == Command.GW_COMMAND_RUN_STATUS_NTF:
69
+ return FrameCommandRunStatusNotification()
70
+ if command == Command.GW_COMMAND_REMAINING_TIME_NTF:
71
+ return FrameCommandRemainingTimeNotification()
72
+ if command == Command.GW_SESSION_FINISHED_NTF:
73
+ return FrameSessionFinishedNotification()
74
+
75
+ if command == Command.GW_PASSWORD_ENTER_REQ:
76
+ return FramePasswordEnterRequest()
77
+ if command == Command.GW_PASSWORD_ENTER_CFM:
78
+ return FramePasswordEnterConfirmation()
79
+
80
+ if command == Command.GW_PASSWORD_CHANGE_REQ:
81
+ return FramePasswordChangeRequest()
82
+ if command == Command.GW_PASSWORD_CHANGE_CFM:
83
+ return FramePasswordChangeConfirmation()
84
+ if command == Command.GW_PASSWORD_CHANGE_NTF:
85
+ return FramePasswordChangeNotification()
86
+
87
+ if command == Command.GW_REBOOT_REQ:
88
+ return FrameGatewayRebootRequest()
89
+ if command == Command.GW_REBOOT_CFM:
90
+ return FrameGatewayRebootConfirmation()
91
+
92
+ if command == Command.GW_SET_FACTORY_DEFAULT_REQ:
93
+ return FrameGatewayFactoryDefaultRequest()
94
+ if command == Command.GW_SET_FACTORY_DEFAULT_CFM:
95
+ return FrameGatewayFactoryDefaultConfirmation()
96
+
97
+ if command == Command.GW_GET_LOCAL_TIME_REQ:
98
+ return FrameGetLocalTimeRequest()
99
+ if command == Command.GW_GET_LOCAL_TIME_CFM:
100
+ return FrameGetLocalTimeConfirmation()
101
+
102
+ if command == Command.GW_CS_DISCOVER_NODES_REQ:
103
+ return FrameDiscoverNodesRequest()
104
+ if command == Command.GW_CS_DISCOVER_NODES_CFM:
105
+ return FrameDiscoverNodesConfirmation()
106
+ if command == Command.GW_CS_DISCOVER_NODES_NTF:
107
+ return FrameDiscoverNodesNotification()
108
+
109
+ if command == Command.GW_GET_SCENE_LIST_REQ:
110
+ return FrameGetSceneListRequest()
111
+ if command == Command.GW_GET_SCENE_LIST_CFM:
112
+ return FrameGetSceneListConfirmation()
113
+ if command == Command.GW_GET_SCENE_LIST_NTF:
114
+ return FrameGetSceneListNotification()
115
+
116
+ if command == Command.GW_GET_NODE_INFORMATION_REQ:
117
+ return FrameGetNodeInformationRequest()
118
+ if command == Command.GW_GET_NODE_INFORMATION_CFM:
119
+ return FrameGetNodeInformationConfirmation()
120
+ if command == Command.GW_GET_NODE_INFORMATION_NTF:
121
+ return FrameGetNodeInformationNotification()
122
+
123
+ if command == Command.GW_GET_ALL_NODES_INFORMATION_REQ:
124
+ return FrameGetAllNodesInformationRequest()
125
+ if command == Command.GW_GET_ALL_NODES_INFORMATION_CFM:
126
+ return FrameGetAllNodesInformationConfirmation()
127
+ if command == Command.GW_GET_ALL_NODES_INFORMATION_NTF:
128
+ return FrameGetAllNodesInformationNotification()
129
+ if command == Command.GW_GET_ALL_NODES_INFORMATION_FINISHED_NTF:
130
+ return FrameGetAllNodesInformationFinishedNotification()
131
+
132
+ if command == Command.GW_ACTIVATE_SCENE_REQ:
133
+ return FrameActivateSceneRequest()
134
+ if command == Command.GW_ACTIVATE_SCENE_CFM:
135
+ return FrameActivateSceneConfirmation()
136
+
137
+ if command == Command.GW_GET_VERSION_REQ:
138
+ return FrameGetVersionRequest()
139
+ if command == Command.GW_GET_VERSION_CFM:
140
+ return FrameGetVersionConfirmation()
141
+ if command == Command.GW_GET_PROTOCOL_VERSION_REQ:
142
+ return FrameGetProtocolVersionRequest()
143
+ if command == Command.GW_GET_PROTOCOL_VERSION_CFM:
144
+ return FrameGetProtocolVersionConfirmation()
145
+
146
+ if command == Command.GW_SET_NODE_NAME_REQ:
147
+ return FrameSetNodeNameRequest()
148
+ if command == Command.GW_SET_NODE_NAME_CFM:
149
+ return FrameSetNodeNameConfirmation()
150
+
151
+ if command == Command.GW_NODE_INFORMATION_CHANGED_NTF:
152
+ return FrameNodeInformationChangedNotification()
153
+
154
+ if command == Command.GW_GET_STATE_REQ:
155
+ return FrameGetStateRequest()
156
+ if command == Command.GW_GET_STATE_CFM:
157
+ return FrameGetStateConfirmation()
158
+
159
+ if command == Command.GW_GET_LIMITATION_STATUS_REQ:
160
+ return FrameGetLimitationStatus()
161
+ if command == Command.GW_GET_LIMITATION_STATUS_CFM:
162
+ return FrameGetLimitationStatusConfirmation()
163
+ if command == Command.GW_LIMITATION_STATUS_NTF:
164
+ return FrameGetLimitationStatusNotification()
165
+
166
+ if command == Command.GW_GET_NETWORK_SETUP_REQ:
167
+ return FrameGetNetworkSetupRequest()
168
+ if command == Command.GW_GET_NETWORK_SETUP_CFM:
169
+ return FrameGetNetworkSetupConfirmation()
170
+
171
+ if command == Command.GW_SET_UTC_REQ:
172
+ return FrameSetUTCRequest()
173
+ if command == Command.GW_SET_UTC_CFM:
174
+ return FrameSetUTCConfirmation()
175
+
176
+ if command == Command.GW_ACTIVATION_LOG_UPDATED_NTF:
177
+ return FrameActivationLogUpdatedNotification()
178
+
179
+ if command == Command.GW_HOUSE_STATUS_MONITOR_ENABLE_REQ:
180
+ return FrameHouseStatusMonitorEnableRequest()
181
+ if command == Command.GW_HOUSE_STATUS_MONITOR_ENABLE_CFM:
182
+ return FrameHouseStatusMonitorEnableConfirmation()
183
+ if command == Command.GW_HOUSE_STATUS_MONITOR_DISABLE_REQ:
184
+ return FrameHouseStatusMonitorDisableRequest()
185
+ if command == Command.GW_HOUSE_STATUS_MONITOR_DISABLE_CFM:
186
+ return FrameHouseStatusMonitorDisableConfirmation()
187
+
188
+ if command == Command.GW_NODE_STATE_POSITION_CHANGED_NTF:
189
+ return FrameNodeStatePositionChangedNotification()
190
+ if command == Command.GW_LEAVE_LEARN_STATE_CFM:
191
+ return FrameLeaveLearnStateConfirmation()
192
+ if command == Command.GW_LEAVE_LEARN_STATE_REQ:
193
+ return FrameLeaveLearnStateRequest()
194
+
195
+ if command == Command.GW_STATUS_REQUEST_REQ:
196
+ return FrameStatusRequestRequest()
197
+ if command == Command.GW_STATUS_REQUEST_CFM:
198
+ return FrameStatusRequestConfirmation()
199
+ if command == Command.GW_STATUS_REQUEST_NTF:
200
+ return FrameStatusRequestNotification()
201
+
202
+ return None
@@ -0,0 +1,76 @@
1
+ """Module for all KLF 200 API frames."""
2
+
3
+ from .alias_array import AliasArray
4
+ # flake8: noqa
5
+ from .frame import FrameBase
6
+ from .frame_activate_scene import (
7
+ ActivateSceneConfirmationStatus, FrameActivateSceneConfirmation,
8
+ FrameActivateSceneRequest)
9
+ from .frame_activation_log_updated import FrameActivationLogUpdatedNotification
10
+ from .frame_command_send import (
11
+ CommandSendConfirmationStatus, FrameCommandRemainingTimeNotification,
12
+ FrameCommandRunStatusNotification, FrameCommandSendConfirmation,
13
+ FrameCommandSendRequest, FrameSessionFinishedNotification)
14
+ from .frame_discover_nodes import (
15
+ FrameDiscoverNodesConfirmation, FrameDiscoverNodesNotification,
16
+ FrameDiscoverNodesRequest)
17
+ from .frame_error_notification import ErrorType, FrameErrorNotification
18
+ from .frame_facory_default import (
19
+ FrameGatewayFactoryDefaultConfirmation, FrameGatewayFactoryDefaultRequest)
20
+ from .frame_get_all_nodes_information import (
21
+ FrameGetAllNodesInformationConfirmation,
22
+ FrameGetAllNodesInformationFinishedNotification,
23
+ FrameGetAllNodesInformationNotification,
24
+ FrameGetAllNodesInformationRequest)
25
+ from .frame_get_limitation import (
26
+ FrameGetLimitationStatus, FrameGetLimitationStatusConfirmation,
27
+ FrameGetLimitationStatusNotification)
28
+ from .frame_get_local_time import (
29
+ FrameGetLocalTimeConfirmation, FrameGetLocalTimeRequest)
30
+ from .frame_get_network_setup import (
31
+ DHCPParameter, FrameGetNetworkSetupConfirmation,
32
+ FrameGetNetworkSetupRequest)
33
+ from .frame_get_node_information import (
34
+ FrameGetNodeInformationConfirmation, FrameGetNodeInformationNotification,
35
+ FrameGetNodeInformationRequest)
36
+ from .frame_get_protocol_version import (
37
+ FrameGetProtocolVersionConfirmation, FrameGetProtocolVersionRequest)
38
+ from .frame_get_scene_list import (
39
+ FrameGetSceneListConfirmation, FrameGetSceneListNotification,
40
+ FrameGetSceneListRequest)
41
+ from .frame_get_state import (
42
+ FrameGetStateConfirmation, FrameGetStateRequest, GatewayState,
43
+ GatewaySubState)
44
+ from .frame_get_version import (
45
+ FrameGetVersionConfirmation, FrameGetVersionRequest)
46
+ from .frame_helper import calc_crc, extract_from_frame
47
+ from .frame_house_status_monitor_disable_cfm import (
48
+ FrameHouseStatusMonitorDisableConfirmation)
49
+ from .frame_house_status_monitor_disable_req import (
50
+ FrameHouseStatusMonitorDisableRequest)
51
+ from .frame_house_status_monitor_enable_cfm import (
52
+ FrameHouseStatusMonitorEnableConfirmation)
53
+ from .frame_house_status_monitor_enable_req import (
54
+ FrameHouseStatusMonitorEnableRequest)
55
+ from .frame_leave_learn_state import (
56
+ FrameLeaveLearnStateConfirmation, FrameLeaveLearnStateRequest,
57
+ LeaveLearnStateConfirmationStatus)
58
+ from .frame_node_information_changed import (
59
+ FrameNodeInformationChangedNotification)
60
+ from .frame_node_state_position_changed_notification import (
61
+ FrameNodeStatePositionChangedNotification)
62
+ from .frame_password_change import (
63
+ FramePasswordChangeConfirmation, FramePasswordChangeNotification,
64
+ FramePasswordChangeRequest, PasswordChangeConfirmationStatus)
65
+ from .frame_password_enter import (
66
+ FramePasswordEnterConfirmation, FramePasswordEnterRequest,
67
+ PasswordEnterConfirmationStatus)
68
+ from .frame_reboot import (
69
+ FrameGatewayRebootConfirmation, FrameGatewayRebootRequest)
70
+ from .frame_set_node_name import (
71
+ FrameSetNodeNameConfirmation, FrameSetNodeNameRequest,
72
+ SetNodeNameConfirmationStatus)
73
+ from .frame_set_utc import FrameSetUTCConfirmation, FrameSetUTCRequest
74
+ from .frame_status_request import (
75
+ FrameStatusRequestConfirmation, FrameStatusRequestNotification,
76
+ FrameStatusRequestRequest)
@@ -0,0 +1,45 @@
1
+ """Module for storing alias array."""
2
+ from typing import List, Optional, Tuple
3
+
4
+ from pyvlx.exception import PyVLXException
5
+
6
+
7
+ class AliasArray:
8
+ """Object for storing alias array."""
9
+
10
+ def __init__(self, raw: Optional[bytes] = None):
11
+ """Initialize alias array."""
12
+ self.alias_array_: List[Tuple[bytes, bytes]] = []
13
+ if raw is not None:
14
+ self.parse_raw(raw)
15
+
16
+ def __str__(self) -> str:
17
+ """Return human readable string."""
18
+ return ", ".join(
19
+ "{:02x}{:02x}={:02x}{:02x}".format(c[0][0], c[0][1], c[1][0], c[1][1])
20
+ for c in self.alias_array_
21
+ )
22
+
23
+ def __bytes__(self) -> bytes:
24
+ """Get raw bytes of alias array."""
25
+ ret = bytes([len(self.alias_array_)])
26
+ for alias in self.alias_array_:
27
+ ret += alias[0] + alias[1]
28
+ ret += bytes((5 - len(self.alias_array_)) * 4)
29
+ return ret
30
+
31
+ def parse_raw(self, raw: bytes) -> None:
32
+ """Parse alias array from raw bytes."""
33
+ if not isinstance(raw, bytes):
34
+ raise PyVLXException("AliasArray::invalid_type_if_raw", type_raw=type(raw))
35
+ if len(raw) != 21:
36
+ raise PyVLXException("AliasArray::invalid_size", size=len(raw))
37
+ nbr_of_alias = raw[0]
38
+ if nbr_of_alias > 5:
39
+ raise PyVLXException(
40
+ "AliasArray::invalid_nbr_of_alias", nbr_of_alias=nbr_of_alias
41
+ )
42
+ for i in range(0, nbr_of_alias):
43
+ self.alias_array_.append(
44
+ (raw[i * 4 + 1 : i * 4 + 3], raw[i * 4 + 3 : i * 4 + 5])
45
+ )
@@ -0,0 +1,56 @@
1
+ """Module for Frames."""
2
+ import struct
3
+
4
+ from pyvlx.const import Command
5
+ from pyvlx.exception import PyVLXException
6
+
7
+ from .frame_helper import calc_crc
8
+
9
+
10
+ class FrameBase:
11
+ """Class for Base Frame."""
12
+
13
+ def __init__(self, command: Command):
14
+ """Initialize Base Frame."""
15
+ self.command = command
16
+
17
+ def __bytes__(self) -> bytes:
18
+ """Get raw bytes of Frame."""
19
+ payload = self.get_payload()
20
+ self.validate_payload_len(payload)
21
+ return self.build_frame(self.command, payload)
22
+
23
+ def validate_payload_len(self, payload: bytes) -> None:
24
+ """Validate payload len."""
25
+ if not hasattr(self, "PAYLOAD_LEN"):
26
+ # No fixed payload len, e.g. within FrameGetSceneListNotification
27
+ return
28
+ # pylint: disable=no-member
29
+ if len(payload) != self.PAYLOAD_LEN:
30
+ raise PyVLXException(
31
+ "Invalid payload len",
32
+ expected_len=self.PAYLOAD_LEN,
33
+ current_len=len(payload),
34
+ frame_type=type(self).__name__,
35
+ )
36
+
37
+ def get_payload(self) -> bytes:
38
+ """Return Payload."""
39
+ return b""
40
+
41
+ def from_payload(self, payload: bytes) -> None:
42
+ """Init frame from binary data."""
43
+
44
+ def __str__(self) -> str:
45
+ """Return human readable string."""
46
+ return "<{}/>".format(type(self).__name__)
47
+
48
+ @staticmethod
49
+ def build_frame(command: Command, payload: bytes) -> bytes:
50
+ """Build raw bytes from command and payload."""
51
+ packet_length = 2 + len(payload) + 1
52
+ ret = struct.pack("BB", 0, packet_length)
53
+ ret += struct.pack(">H", command.value)
54
+ ret += payload
55
+ ret += struct.pack("B", calc_crc(ret))
56
+ return ret