solarlog-cli 0.1.4__tar.gz → 0.1.6__tar.gz
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.
- {solarlog_cli-0.1.4 → solarlog_cli-0.1.6}/PKG-INFO +1 -1
- {solarlog_cli-0.1.4 → solarlog_cli-0.1.6}/pyproject.toml +1 -1
- {solarlog_cli-0.1.4 → solarlog_cli-0.1.6}/src/solarlog_cli/solarlog_client.py +2 -2
- {solarlog_cli-0.1.4 → solarlog_cli-0.1.6}/src/solarlog_cli/solarlog_connector.py +19 -18
- solarlog_cli-0.1.4/src/solarlog_cli/utils.py +0 -58
- {solarlog_cli-0.1.4 → solarlog_cli-0.1.6}/.github/workflows/pylint.yml +0 -0
- {solarlog_cli-0.1.4 → solarlog_cli-0.1.6}/.github/workflows/python-publish.yml +0 -0
- {solarlog_cli-0.1.4 → solarlog_cli-0.1.6}/.github/workflows/ruff.yml +0 -0
- {solarlog_cli-0.1.4 → solarlog_cli-0.1.6}/.gitignore +0 -0
- {solarlog_cli-0.1.4 → solarlog_cli-0.1.6}/LICENSE +0 -0
- {solarlog_cli-0.1.4 → solarlog_cli-0.1.6}/README.md +0 -0
- {solarlog_cli-0.1.4 → solarlog_cli-0.1.6}/requirements.txt +0 -0
- {solarlog_cli-0.1.4 → solarlog_cli-0.1.6}/src/solarlog_cli/__init__.py +0 -0
- {solarlog_cli-0.1.4 → solarlog_cli-0.1.6}/src/solarlog_cli/solarlog_exceptions.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: solarlog_cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: Python library to access the Solar-Log
|
|
5
5
|
Project-URL: Repository, https://github.com/dontinelli/solarlog_cli.git
|
|
6
6
|
Project-URL: Issues, https://github.com/dontinelli/solarlog_cli/issues
|
|
@@ -20,7 +20,7 @@ _LOGGER = logging.getLogger(__name__)
|
|
|
20
20
|
class Client:
|
|
21
21
|
"""Client class to access Solar-Log."""
|
|
22
22
|
|
|
23
|
-
def __init__(self, host: str):
|
|
23
|
+
def __init__(self, host: str) -> None:
|
|
24
24
|
self.host: str = host
|
|
25
25
|
|
|
26
26
|
self.session: ClientSession = ClientSession()
|
|
@@ -85,7 +85,7 @@ class Client:
|
|
|
85
85
|
|
|
86
86
|
return json_response
|
|
87
87
|
|
|
88
|
-
async def get_basic_data(self) -> dict[str,
|
|
88
|
+
async def get_basic_data(self) -> dict[str, int | float | datetime]:
|
|
89
89
|
"""Get basic data from Solar-Log."""
|
|
90
90
|
|
|
91
91
|
raw_data: dict = await self.execute_http_request({801: {170: None}})
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
"""Connector class to manage access to Solar-Log."""
|
|
2
2
|
|
|
3
|
-
from datetime import timezone
|
|
4
|
-
|
|
3
|
+
from datetime import datetime, timezone
|
|
4
|
+
import logging
|
|
5
5
|
from zoneinfo import ZoneInfo
|
|
6
6
|
|
|
7
7
|
from .solarlog_client import Client
|
|
8
8
|
from .solarlog_exceptions import SolarLogUpdateError
|
|
9
9
|
|
|
10
|
+
_LOGGER = logging.getLogger(__name__)
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
class SolarLogConnector:
|
|
12
14
|
"""Connector class to access Solar-Log."""
|
|
@@ -30,10 +32,10 @@ class SolarLogConnector:
|
|
|
30
32
|
|
|
31
33
|
return await self.client.test_connection()
|
|
32
34
|
|
|
33
|
-
async def update_data(self) -> dict[str,
|
|
35
|
+
async def update_data(self) -> dict[str, int | float | datetime]:
|
|
34
36
|
"""Get data from Solar-Log."""
|
|
35
37
|
|
|
36
|
-
data: dict = await self.client.get_basic_data()
|
|
38
|
+
data: dict[str, int | float | datetime] = await self.client.get_basic_data()
|
|
37
39
|
|
|
38
40
|
if data["last_updated"].year == 1999:
|
|
39
41
|
raise SolarLogUpdateError(
|
|
@@ -42,14 +44,15 @@ class SolarLogConnector:
|
|
|
42
44
|
|
|
43
45
|
data["last_updated"] = data["last_updated"].replace(tzinfo=self.timezone)
|
|
44
46
|
|
|
45
|
-
|
|
47
|
+
_LOGGER.debug("Basic data updated: %s",data)
|
|
46
48
|
if self.extended_data:
|
|
47
49
|
data |= await self.client.get_energy()
|
|
48
50
|
if self._device_enabled != {} and self._device_enabled is not None:
|
|
49
51
|
data |= {"devices": await self.update_inverter_data()}
|
|
50
|
-
|
|
52
|
+
_LOGGER.debug("Extended data updated: %s",data)
|
|
51
53
|
|
|
52
54
|
#calculated values (for downward compatibility)
|
|
55
|
+
data |= {"alternator_loss": data.get("power_dc") - data.get("power_ac")}
|
|
53
56
|
if data.get("power_dc") != 0:
|
|
54
57
|
data |= {"efficiency": data.get("power_ac") / data.get("power_dc")}
|
|
55
58
|
if data.get("power_ac") != 0:
|
|
@@ -58,10 +61,8 @@ class SolarLogConnector:
|
|
|
58
61
|
else:
|
|
59
62
|
data |= {"usage": 0.0}
|
|
60
63
|
data |= {"power_available": 0.0}
|
|
61
|
-
data |= {"alternator_loss": data.get("power_dc") - data.get("power_ac")}
|
|
62
|
-
|
|
63
64
|
if data.get("total_power") != 0:
|
|
64
|
-
data |= {"capacity":
|
|
65
|
+
data |= {"capacity": data.get("power_dc") / data.get("total_power")}
|
|
65
66
|
|
|
66
67
|
return data
|
|
67
68
|
|
|
@@ -74,32 +75,28 @@ class SolarLogConnector:
|
|
|
74
75
|
|
|
75
76
|
for key, value in self._device_enabled.items():
|
|
76
77
|
device_list[int(key)] |= {"enabled": value}
|
|
77
|
-
|
|
78
|
+
_LOGGER.debug("Device list: %s",device_list)
|
|
78
79
|
self._device_list = device_list
|
|
79
80
|
|
|
80
81
|
return device_list
|
|
81
82
|
|
|
82
|
-
async def update_inverter_data(self) -> dict[int, dict[str,
|
|
83
|
+
async def update_inverter_data(self) -> dict[int, dict[str, float]]:
|
|
83
84
|
"""Update device specific data."""
|
|
84
|
-
data: dict[int, dict[str,
|
|
85
|
-
# print(self._device_enabled)
|
|
85
|
+
data: dict[int, dict[str, float]] = {}
|
|
86
86
|
raw_data = await self.client.get_power_per_inverter()
|
|
87
|
-
# print(f"power: {raw_data}")
|
|
88
87
|
for key, value in raw_data.items():
|
|
89
88
|
key = int(key)
|
|
90
89
|
if self._device_enabled.get(key, False):
|
|
91
90
|
data |= {key: {"current_power": float(value)}}
|
|
92
91
|
|
|
93
92
|
raw_data = await self.client.get_energy_per_inverter()
|
|
94
|
-
# print(f"energy: {raw_data}")
|
|
95
93
|
for key, value in raw_data.items():
|
|
96
|
-
# print(f"key: {key}, value: {value}, enabled: {self._device_enabled[key]}")
|
|
97
94
|
if self._device_enabled[key]:
|
|
98
95
|
if key in data:
|
|
99
96
|
data[key].update({"consumption_year": float(value)})
|
|
100
97
|
else:
|
|
101
98
|
data |= {key: {"consumption_year": float(value)}}
|
|
102
|
-
|
|
99
|
+
_LOGGER.debug("Inverter data updated: %s",data)
|
|
103
100
|
|
|
104
101
|
return data
|
|
105
102
|
|
|
@@ -115,7 +112,7 @@ class SolarLogConnector:
|
|
|
115
112
|
|
|
116
113
|
def device_name(self, device_id: int) -> str:
|
|
117
114
|
"""Get name of Solar-Log attached device."""
|
|
118
|
-
|
|
115
|
+
_LOGGER.debug("Device list: %s; id: %s",self._device_list, device_id)
|
|
119
116
|
if device_id in self._device_list:
|
|
120
117
|
return self._device_list[device_id]["name"]
|
|
121
118
|
|
|
@@ -126,3 +123,7 @@ class SolarLogConnector:
|
|
|
126
123
|
if device_id is None:
|
|
127
124
|
return self._device_enabled
|
|
128
125
|
return self._device_enabled[device_id]
|
|
126
|
+
|
|
127
|
+
def set_enabled_devices(self, device_enabled: dict[int, bool]) -> None:
|
|
128
|
+
"""Set enabled devices."""
|
|
129
|
+
self._device_enabled = device_enabled
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
"""Utility functions for the FYTA integration."""
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def safe_get(plant_data, key_path, expected_type):
|
|
5
|
-
"""Get a value from a nested dictionary and cast it to the expected type.
|
|
6
|
-
|
|
7
|
-
Args:
|
|
8
|
-
plant_data: The dictionary to get the value from.
|
|
9
|
-
key_path: The path to the value in the dictionary. Seüarated by dots.
|
|
10
|
-
expected_type: The expected type of the value (int, float, bool and str supported).
|
|
11
|
-
|
|
12
|
-
Returns: The value from the dictionary or None if the value is not found or the type is not
|
|
13
|
-
as expected.
|
|
14
|
-
"""
|
|
15
|
-
keys = key_path.split(".")
|
|
16
|
-
value = plant_data
|
|
17
|
-
try:
|
|
18
|
-
for key in keys:
|
|
19
|
-
value = value.get(key)
|
|
20
|
-
if value is None:
|
|
21
|
-
return None
|
|
22
|
-
except AttributeError:
|
|
23
|
-
return None
|
|
24
|
-
return_value = None
|
|
25
|
-
if expected_type == int:
|
|
26
|
-
return_value = __get_int(value)
|
|
27
|
-
if expected_type == float:
|
|
28
|
-
return_value = __get_float(value)
|
|
29
|
-
if expected_type == bool:
|
|
30
|
-
return_value = __get_bool(value)
|
|
31
|
-
if expected_type == str:
|
|
32
|
-
return_value = str(value)
|
|
33
|
-
return return_value
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def __get_bool(value):
|
|
37
|
-
if isinstance(value, bool):
|
|
38
|
-
return value
|
|
39
|
-
if isinstance(value, str):
|
|
40
|
-
if value.lower() == "true":
|
|
41
|
-
return True
|
|
42
|
-
if value.lower() == "false":
|
|
43
|
-
return False
|
|
44
|
-
return None
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def __get_float(value):
|
|
48
|
-
try:
|
|
49
|
-
return float(value)
|
|
50
|
-
except (ValueError, TypeError):
|
|
51
|
-
return None
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def __get_int(value):
|
|
55
|
-
try:
|
|
56
|
-
return int(value)
|
|
57
|
-
except (ValueError, TypeError):
|
|
58
|
-
return None
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|