Skip to content

Commit fb6aa22

Browse files
authored
Merge branch 'main' into issue/168/obsolete
2 parents de8e5b1 + e307db8 commit fb6aa22

21 files changed

+3975
-48
lines changed

.github/workflows/pytest.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ jobs:
1717
python-version: "3.11"
1818
- name: Install pytest
1919
run: pip install pytest pytest-cov
20+
- name: Install dependencies
21+
run: pip install .
2022
- name: Run pytest
2123
# yamllint disable rule:line-length
2224
run: |
File renamed without changes.

MANIFEST.in

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# MANIFEST.in
2+
# This file tells setuptools which additional non‑Python files should be
3+
# included in the source distribution (sdist) and wheel.
4+
# We explicitly include our own LICENSE and NOTICE files, as well as
5+
# third‑party license texts stored in the licenses/ directory.
6+
7+
include LICENSE.md
8+
include NOTICE.md
9+
recursive-include licenses *

NOTICE.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# NOTICE
2+
3+
Project: luxtronik
4+
License: MIT License
5+
Copyright (c) 2018 Bouni
6+
7+
---
8+
9+
This project includes software developed by third parties.
10+
The following components are used and are subject to their respective licenses:
11+
12+
1. pyModbusTCP (Version 0.3.0)
13+
License: [MIT License][1]
14+
Copyright (c) 2014 l.lefebvre
15+
16+
Each of the above components is used in accordance with the terms
17+
of its license. Full license texts are available in the respective repositories
18+
or if necessary in the `licenses/` directory of this project.
19+
20+
[1]: https://github.com/sourceperl/pyModbusTCP/blob/v0.3.0/LICENSE
21+
22+
This NOTICE file is provided for informational purposes
23+
only and does not modify any license terms.

luxtronik/calculations.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,5 +317,6 @@ def __init__(self):
317317
264: Unknown("Unknown_Calculation_264"),
318318
265: Unknown("Unknown_Calculation_265"),
319319
266: Unknown("Unknown_Calculation_266"),
320-
267: Celsius(["Desired_Room_Temperature", "Unknown_Calculation_267"]),
320+
267: Celsius("Desired_Room_Temperature"),
321+
268: Power("AC_Power_Input")
321322
}

luxtronik/common.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from threading import RLock
2+
3+
# Global lock to synchronize access to the hosts_locks dictionary
4+
_management_lock = RLock()
5+
_hosts_locks = {}
6+
7+
def get_host_lock(host):
8+
"""
9+
Retrieve the unique lock object associated with a given host.
10+
The same thread can acquire a RLock as often as desired.
11+
12+
If no lock exists for the host, a new one is created in a thread-safe manner.
13+
14+
Args:
15+
host (str): Hostname or IP address.
16+
17+
Returns:
18+
RLock: The lock object dedicated to the given host.
19+
"""
20+
# Ensure a dedicated lock is created for each IP.
21+
with _management_lock:
22+
if host not in _hosts_locks:
23+
_hosts_locks[host] = RLock()
24+
return _hosts_locks[host]

luxtronik/datatypes.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,112 @@ def to_heatpump(cls, value):
874874

875875
return val
876876

877+
class HeatPumpState(SelectionBase):
878+
"""HeatPumpState datatype, converts from and to list of HeatPumpState codes."""
879+
880+
datatype_class = "selection"
881+
882+
codes = {
883+
0: "Idle", # Heatpump is idle
884+
1: "Running", # Heatpump is running
885+
}
886+
887+
class ModeState(SelectionBase):
888+
"""ModeState datatype, converts from and to list of ModeState codes."""
889+
890+
datatype_class = "selection"
891+
892+
codes = {
893+
0: "Disabled", # Heating / Hot water is disabled
894+
1: "No request", # Heating / Hot water currently not requested
895+
2: "Requested", # Heating / Hot water requested but currently not running
896+
3: "Running", # Heating / Hot water running
897+
}
898+
899+
class ControlMode(SelectionBase):
900+
"""ControlMode datatype, converts from and to list of ControlMode codes."""
901+
902+
datatype_class = "selection"
903+
904+
codes = {
905+
0: "Off", # System value is used
906+
1: "Setpoint", # Setpoint register value is used
907+
2: "Offset", # System values + offset register value is used
908+
3: "Level", # System values + smart-home-interface-settings
909+
# register value is used
910+
}
911+
912+
913+
class LpcMode(SelectionBase):
914+
"""LpcMode datatype, converts from and to list of LpcMode codes."""
915+
916+
datatype_class = "selection"
917+
918+
codes = {
919+
0: "No limit",
920+
1: "Soft limit",
921+
2: "Hard limit",
922+
}
923+
924+
925+
class LockMode(SelectionBase):
926+
"""LockMode datatype, converts from and to list of LockMode codes."""
927+
928+
datatype_class = "selection"
929+
930+
codes = {
931+
0: "Off", # Function is not locked
932+
1: "On", # Function is locked
933+
}
934+
935+
class OnOffMode(SelectionBase):
936+
"""OnOffMode datatype, converts from and to list of OnOffMode codes."""
937+
938+
datatype_class = "selection"
939+
940+
codes = {
941+
0: "Off", # Function deactivated
942+
1: "On", # Function activated
943+
}
944+
945+
class LevelMode(SelectionBase):
946+
"""LevelMode datatype, converts from and to list of LevelMode codes."""
947+
948+
datatype_class = "selection"
949+
950+
codes = {
951+
0: "Normal", # No correction
952+
1: "Increased", # Increase the temperature by the values
953+
# within the smart-home-interface-settings
954+
# TODO: Function unknown – requires further analysis
955+
2: "Increased2", # Increase the temperature by the values
956+
# within the smart-home-interface-settings
957+
# TODO: Function unknown – requires further analysis
958+
3: "Decreased", # Decrease the temperature by the values
959+
# within the smart-home-interface-settings
960+
# TODO: Function unknown – requires further analysis
961+
}
962+
963+
class PowerLimit(ScalingBase):
964+
"""PowerLimit datatype, converts from and to PowerLimit."""
965+
966+
datatype_class = "power"
967+
datatype_unit = "kW"
968+
scaling_factor = 0.1
969+
970+
971+
class FullVersion(Base):
972+
"""FullVersion datatype, converts from and to a RBEVersion"""
973+
974+
datatype_class = "version"
975+
976+
@classmethod
977+
def from_heatpump(cls, value):
978+
if isinstance(value, list) and len(value) >= 3:
979+
return f"{value[0]}.{value[1]}.{value[2]}"
980+
else:
981+
return "0"
982+
877983

878984
class Unknown(Base):
879985
"""Unknown datatype, fallback for unknown data."""

0 commit comments

Comments
 (0)