solax-py-library 1.0.0.24__py3-none-any.whl → 1.0.0.2502__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.
- solax_py_library/__init__.py +1 -1
- solax_py_library/device/constant/inverter_model_info.py +312 -312
- solax_py_library/device/core/interver/__init__.py +36 -36
- solax_py_library/device/core/interver/base.py +215 -215
- solax_py_library/device/types/inverter_config.py +41 -41
- solax_py_library/device/types/modbus_point.py +30 -30
- solax_py_library/exception.py +10 -10
- solax_py_library/smart_scene/__init__.py +0 -0
- solax_py_library/smart_scene/constant/__init__.py +0 -0
- solax_py_library/smart_scene/constant/message_entry.py +338 -0
- solax_py_library/smart_scene/core/__init__.py +0 -0
- solax_py_library/smart_scene/core/action/__init__.py +0 -0
- solax_py_library/smart_scene/core/condition/__init__.py +0 -0
- solax_py_library/smart_scene/core/condition/base.py +12 -0
- solax_py_library/smart_scene/core/condition/cabinet_condition.py +104 -0
- solax_py_library/smart_scene/core/condition/date_condition.py +26 -0
- solax_py_library/smart_scene/core/condition/price_condition.py +105 -0
- solax_py_library/smart_scene/core/condition/system_condition.py +41 -0
- solax_py_library/smart_scene/core/condition/weather_condition.py +67 -0
- solax_py_library/smart_scene/exceptions/__init__.py +0 -0
- solax_py_library/smart_scene/exceptions/price.py +5 -0
- solax_py_library/smart_scene/exceptions/smart_scene.py +81 -0
- solax_py_library/smart_scene/exceptions/weather.py +5 -0
- solax_py_library/smart_scene/types/__init__.py +0 -0
- solax_py_library/smart_scene/types/action.py +156 -0
- solax_py_library/smart_scene/types/condition.py +293 -0
- solax_py_library/smart_scene/types/smart_scene_content.py +173 -0
- solax_py_library/snap_shot/__init__.py +3 -3
- solax_py_library/snap_shot/constant/__init__.py +5 -5
- solax_py_library/snap_shot/constant/crc_table.py +258 -258
- solax_py_library/snap_shot/core/__init__.py +9 -9
- solax_py_library/snap_shot/core/base_modbus.py +14 -14
- solax_py_library/snap_shot/exceptions/__init__.py +3 -3
- solax_py_library/snap_shot/exceptions/snap_shot.py +9 -9
- solax_py_library/snap_shot/types/__init__.py +15 -15
- solax_py_library/snap_shot/types/address.py +39 -39
- solax_py_library/test/__init__.py +0 -0
- solax_py_library/test/test_utils/__init__.py +0 -0
- solax_py_library/test/test_utils/test_cloud_client.py +14 -0
- solax_py_library/upload/__init__.py +3 -3
- solax_py_library/upload/api/__init__.py +3 -3
- solax_py_library/upload/api/service.py +24 -24
- solax_py_library/upload/core/__init__.py +3 -3
- solax_py_library/upload/core/data_adapter/__init__.py +5 -5
- solax_py_library/upload/core/data_adapter/base.py +9 -9
- solax_py_library/upload/core/data_adapter/csv.py +26 -26
- solax_py_library/upload/core/upload_service/__init__.py +15 -15
- solax_py_library/upload/core/upload_service/base.py +43 -43
- solax_py_library/upload/exceptions/__init__.py +8 -8
- solax_py_library/upload/exceptions/upload_error.py +21 -21
- solax_py_library/upload/test/test_ftp.py +113 -113
- solax_py_library/upload/types/__init__.py +11 -11
- solax_py_library/upload/types/client.py +19 -19
- solax_py_library/upload/types/ftp.py +37 -37
- solax_py_library/utils/cloud_client.py +210 -0
- solax_py_library/utils/common.py +38 -38
- solax_py_library/utils/struct_util.py +30 -30
- solax_py_library/utils/time_util.py +5 -0
- {solax_py_library-1.0.0.24.dist-info → solax_py_library-1.0.0.2502.dist-info}/METADATA +2 -1
- solax_py_library-1.0.0.2502.dist-info/RECORD +71 -0
- solax_py_library-1.0.0.24.dist-info/RECORD +0 -46
- {solax_py_library-1.0.0.24.dist-info → solax_py_library-1.0.0.2502.dist-info}/WHEEL +0 -0
@@ -1,36 +1,36 @@
|
|
1
|
-
from .base import InverterProtocol
|
2
|
-
|
3
|
-
|
4
|
-
inverter_protocol_map = {}
|
5
|
-
|
6
|
-
|
7
|
-
def register_protocol(protocol_class: InverterProtocol):
|
8
|
-
if protocol_class.inverter_model is None:
|
9
|
-
raise RuntimeError("未找到对应的设备类型")
|
10
|
-
inverter_protocol_map[protocol_class.inverter_model] = protocol_class
|
11
|
-
|
12
|
-
|
13
|
-
def ProtocolFactory(inverter_model: int, *args, **kwargs) -> InverterProtocol:
|
14
|
-
"""
|
15
|
-
创建协议实例。
|
16
|
-
inverter_model: 逆变器类型
|
17
|
-
device_info: 设备信息。
|
18
|
-
data: 数据。
|
19
|
-
"""
|
20
|
-
protocol_class = inverter_protocol_map.get(inverter_model)
|
21
|
-
if not protocol_class:
|
22
|
-
raise ValueError(f"未找到名为 '{str(inverter_model)}' 的协议")
|
23
|
-
return protocol_class(*args, **kwargs)
|
24
|
-
|
25
|
-
|
26
|
-
def match_pcs(operate_queue, slave_num):
|
27
|
-
for device_model in inverter_protocol_map.keys():
|
28
|
-
client = ProtocolFactory(device_model)
|
29
|
-
sn_data = client.read_sn(operate_queue.modbus_rtu, slave_num)
|
30
|
-
if not sn_data:
|
31
|
-
continue
|
32
|
-
sn = get_char(sn_data)
|
33
|
-
inverter_model, _ = client.parse_sn(sn)
|
34
|
-
if inverter_model:
|
35
|
-
return inverter_model, sn
|
36
|
-
return None, None
|
1
|
+
from .base import InverterProtocol
|
2
|
+
|
3
|
+
|
4
|
+
inverter_protocol_map = {}
|
5
|
+
|
6
|
+
|
7
|
+
def register_protocol(protocol_class: InverterProtocol):
|
8
|
+
if protocol_class.inverter_model is None:
|
9
|
+
raise RuntimeError("未找到对应的设备类型")
|
10
|
+
inverter_protocol_map[protocol_class.inverter_model] = protocol_class
|
11
|
+
|
12
|
+
|
13
|
+
def ProtocolFactory(inverter_model: int, *args, **kwargs) -> InverterProtocol:
|
14
|
+
"""
|
15
|
+
创建协议实例。
|
16
|
+
inverter_model: 逆变器类型
|
17
|
+
device_info: 设备信息。
|
18
|
+
data: 数据。
|
19
|
+
"""
|
20
|
+
protocol_class = inverter_protocol_map.get(inverter_model)
|
21
|
+
if not protocol_class:
|
22
|
+
raise ValueError(f"未找到名为 '{str(inverter_model)}' 的协议")
|
23
|
+
return protocol_class(*args, **kwargs)
|
24
|
+
|
25
|
+
|
26
|
+
def match_pcs(operate_queue, slave_num):
|
27
|
+
for device_model in inverter_protocol_map.keys():
|
28
|
+
client = ProtocolFactory(device_model)
|
29
|
+
sn_data = client.read_sn(operate_queue.modbus_rtu, slave_num)
|
30
|
+
if not sn_data:
|
31
|
+
continue
|
32
|
+
sn = get_char(sn_data)
|
33
|
+
inverter_model, _ = client.parse_sn(sn)
|
34
|
+
if inverter_model:
|
35
|
+
return inverter_model, sn
|
36
|
+
return None, None
|
@@ -1,215 +1,215 @@
|
|
1
|
-
import json
|
2
|
-
from abc import ABCMeta, abstractmethod
|
3
|
-
from collections import OrderedDict
|
4
|
-
from datetime import datetime
|
5
|
-
from typing import List, Union
|
6
|
-
|
7
|
-
from pydantic.class_validators import Validator
|
8
|
-
|
9
|
-
from solax_py_library.device.types.inverter_config import InverterConfig, InverterPoint
|
10
|
-
from solax_py_library.device.types.modbus_point import WriteModbusPoint, ReadModbusPoint
|
11
|
-
from solax_py_library.utils.common import round_value
|
12
|
-
from solax_py_library.utils.struct_util import unpack
|
13
|
-
|
14
|
-
|
15
|
-
class InverterProtocol(metaclass=ABCMeta):
|
16
|
-
inverter_model: None
|
17
|
-
|
18
|
-
def __init__(self, point_config):
|
19
|
-
self.col_name_index_map = OrderedDict()
|
20
|
-
self.col_index_name_map = OrderedDict()
|
21
|
-
self.col_id_index_map = {}
|
22
|
-
self.sn_config = None
|
23
|
-
self.shutdown_config = None
|
24
|
-
self.boot_up_config = None
|
25
|
-
self.time_config = None
|
26
|
-
self.version_config = None
|
27
|
-
self.error_map = None
|
28
|
-
self._prepare(point_config)
|
29
|
-
|
30
|
-
def _prepare(self, point_config: str):
|
31
|
-
point_config = json.loads(point_config)
|
32
|
-
self.real_data_start_address = None
|
33
|
-
self.real_data_end_address = None
|
34
|
-
try:
|
35
|
-
point_config = InverterConfig(**point_config)
|
36
|
-
except Validator as e:
|
37
|
-
print(e)
|
38
|
-
for index, real_point in enumerate(point_config.real_data):
|
39
|
-
point_key = real_point.point_key
|
40
|
-
point_id = real_point.point_id
|
41
|
-
self.col_name_index_map[point_key] = real_point
|
42
|
-
self.col_index_name_map[point_id] = real_point
|
43
|
-
self.col_id_index_map[point_id] = index
|
44
|
-
self.real_data_start_address = min(
|
45
|
-
self.real_data_start_address, real_point.starting_address
|
46
|
-
)
|
47
|
-
self.real_data_end_address = max(
|
48
|
-
self.real_data_end_address,
|
49
|
-
real_point.starting_address + real_point.quantity_of_x - 1,
|
50
|
-
)
|
51
|
-
|
52
|
-
self.sn_config = point_config.other_data.sn
|
53
|
-
self.shutdown_config = point_config.other_data.shutdown
|
54
|
-
self.boot_up_config = point_config.other_data.boot_up
|
55
|
-
self.time_config = point_config.other_data.time
|
56
|
-
self.version_config = point_config.other_data.version
|
57
|
-
|
58
|
-
self.error_map = point_config.error_map
|
59
|
-
|
60
|
-
def read_real_data(self, modbus_client, slave):
|
61
|
-
real_data = self._execute_modbus(
|
62
|
-
modbus_client,
|
63
|
-
slave,
|
64
|
-
ReadModbusPoint(
|
65
|
-
starting_address=self.real_data_start_address,
|
66
|
-
quantity_of_x=self.real_data_end_address
|
67
|
-
- self.real_data_start_address
|
68
|
-
+ 1,
|
69
|
-
function_code=InverterPoint.function_code,
|
70
|
-
),
|
71
|
-
)
|
72
|
-
ret_real_data = {}
|
73
|
-
for point_id, point_info in self.col_index_name_map.items():
|
74
|
-
offset = point_info.starting_address
|
75
|
-
data = real_data[offset : offset + point_info.quantity_of_x]
|
76
|
-
ret_real_data[point_id] = self._parse_point_data(point_info, data)
|
77
|
-
return ret_real_data
|
78
|
-
|
79
|
-
def read_real_data_to_list(self, modbus_client, slave):
|
80
|
-
real_data = self.read_real_data(modbus_client, slave)
|
81
|
-
return list(real_data.values())
|
82
|
-
|
83
|
-
def _parse_point_data(self, point_info: InverterPoint, point_data):
|
84
|
-
value = unpack(
|
85
|
-
point_data, data_format=point_info.register_dataformat, reversed=True
|
86
|
-
)
|
87
|
-
accuracy = point_info.accuracy
|
88
|
-
return round_value(value * accuracy, 3)
|
89
|
-
|
90
|
-
def get_data_by_point_id_from_list(self, point_id, real_data):
|
91
|
-
point_index = self.col_id_index_map[point_id]
|
92
|
-
return real_data[point_index]
|
93
|
-
|
94
|
-
@abstractmethod
|
95
|
-
def get_real_power(self, read_data):
|
96
|
-
raise NotImplementedError()
|
97
|
-
|
98
|
-
@abstractmethod
|
99
|
-
def get_error_data(self, read_data):
|
100
|
-
raise NotImplementedError()
|
101
|
-
|
102
|
-
@abstractmethod
|
103
|
-
def parse_pcs_status(self, read_data):
|
104
|
-
...
|
105
|
-
|
106
|
-
@abstractmethod
|
107
|
-
def parse_error_code(self, error_data):
|
108
|
-
...
|
109
|
-
|
110
|
-
def error_to_alarm_code(self, error_codes: List[int]):
|
111
|
-
if not self.error_map:
|
112
|
-
return error_codes
|
113
|
-
alarm_codes = []
|
114
|
-
for error_code in error_codes:
|
115
|
-
if alarm_code := self.error_map.get(error_code):
|
116
|
-
alarm_codes.append(alarm_code)
|
117
|
-
return alarm_codes
|
118
|
-
|
119
|
-
def pv_power_data(self, real_data):
|
120
|
-
...
|
121
|
-
|
122
|
-
def get_pv_capacity(self, real_data, history_data):
|
123
|
-
...
|
124
|
-
|
125
|
-
def get_active_power(self, read_data):
|
126
|
-
...
|
127
|
-
|
128
|
-
def get_reactive_power(self, read_data):
|
129
|
-
...
|
130
|
-
|
131
|
-
# ============================== read or write =========================================
|
132
|
-
|
133
|
-
def _execute_modbus(
|
134
|
-
self,
|
135
|
-
modbus_client,
|
136
|
-
slave_num,
|
137
|
-
point_info: Union[WriteModbusPoint, ReadModbusPoint],
|
138
|
-
output_value=None,
|
139
|
-
):
|
140
|
-
try:
|
141
|
-
ret = modbus_client.read_and_write(
|
142
|
-
slave_num,
|
143
|
-
**point_info.dict(
|
144
|
-
include={"starting_address", "quantity_of_x", "function_code"}
|
145
|
-
),
|
146
|
-
output_value=output_value,
|
147
|
-
)
|
148
|
-
except Exception as e:
|
149
|
-
print(e)
|
150
|
-
return ret
|
151
|
-
|
152
|
-
def shutdown(self, modbus_client, slave_num):
|
153
|
-
self._execute_modbus(
|
154
|
-
modbus_client,
|
155
|
-
slave_num,
|
156
|
-
self.shutdown_config,
|
157
|
-
output_value=self.shutdown_config.output_value,
|
158
|
-
)
|
159
|
-
|
160
|
-
def boot_up(self, modbus_client, slave_num):
|
161
|
-
self._execute_modbus(
|
162
|
-
modbus_client,
|
163
|
-
slave_num,
|
164
|
-
self.boot_up_config,
|
165
|
-
output_value=self.boot_up_config.output_value,
|
166
|
-
)
|
167
|
-
|
168
|
-
def read_sn(self, modbus_client, slave_num):
|
169
|
-
return self._execute_modbus(modbus_client, slave_num, self.sn_config)
|
170
|
-
|
171
|
-
def read_soft_version_and_hard_version(self, modbus_client, slave_num):
|
172
|
-
soft_inv_version = self.read_soft_version(modbus_client, slave_num)
|
173
|
-
hard_inv_version = self.read_hard_version(modbus_client, slave_num)
|
174
|
-
return soft_inv_version, hard_inv_version
|
175
|
-
|
176
|
-
def read_soft_version(self, modbus_client, slave_num):
|
177
|
-
return self._execute_modbus(
|
178
|
-
modbus_client, slave_num, self.version_config.software
|
179
|
-
)
|
180
|
-
|
181
|
-
def read_hard_version(self, modbus_client, slave_num):
|
182
|
-
return self._execute_modbus(
|
183
|
-
modbus_client, slave_num, self.version_config.hardware
|
184
|
-
)
|
185
|
-
|
186
|
-
def get_upgrade_value(self, crc, file_size):
|
187
|
-
crc_nums = [crc[1], crc[0]]
|
188
|
-
file_size = [file_size[1], file_size[0]]
|
189
|
-
value = (
|
190
|
-
[self.inverter_model]
|
191
|
-
+ crc_nums
|
192
|
-
+ [1, 0, 0, 0, 0, 0, 0]
|
193
|
-
+ file_size
|
194
|
-
+ [1, 0, 0]
|
195
|
-
)
|
196
|
-
return value
|
197
|
-
|
198
|
-
def write_pcs_time(self, modbus_client, slave_num):
|
199
|
-
self._execute_modbus(
|
200
|
-
modbus_client,
|
201
|
-
slave_num,
|
202
|
-
self.time_config,
|
203
|
-
output_value=self._build_pcs_time_value(),
|
204
|
-
)
|
205
|
-
|
206
|
-
def _build_pcs_time_value(self):
|
207
|
-
cur_time = datetime.now()
|
208
|
-
return [
|
209
|
-
cur_time.year,
|
210
|
-
cur_time.month,
|
211
|
-
cur_time.day,
|
212
|
-
cur_time.hour,
|
213
|
-
cur_time.minute,
|
214
|
-
cur_time.second,
|
215
|
-
]
|
1
|
+
import json
|
2
|
+
from abc import ABCMeta, abstractmethod
|
3
|
+
from collections import OrderedDict
|
4
|
+
from datetime import datetime
|
5
|
+
from typing import List, Union
|
6
|
+
|
7
|
+
from pydantic.class_validators import Validator
|
8
|
+
|
9
|
+
from solax_py_library.device.types.inverter_config import InverterConfig, InverterPoint
|
10
|
+
from solax_py_library.device.types.modbus_point import WriteModbusPoint, ReadModbusPoint
|
11
|
+
from solax_py_library.utils.common import round_value
|
12
|
+
from solax_py_library.utils.struct_util import unpack
|
13
|
+
|
14
|
+
|
15
|
+
class InverterProtocol(metaclass=ABCMeta):
|
16
|
+
inverter_model: None
|
17
|
+
|
18
|
+
def __init__(self, point_config):
|
19
|
+
self.col_name_index_map = OrderedDict()
|
20
|
+
self.col_index_name_map = OrderedDict()
|
21
|
+
self.col_id_index_map = {}
|
22
|
+
self.sn_config = None
|
23
|
+
self.shutdown_config = None
|
24
|
+
self.boot_up_config = None
|
25
|
+
self.time_config = None
|
26
|
+
self.version_config = None
|
27
|
+
self.error_map = None
|
28
|
+
self._prepare(point_config)
|
29
|
+
|
30
|
+
def _prepare(self, point_config: str):
|
31
|
+
point_config = json.loads(point_config)
|
32
|
+
self.real_data_start_address = None
|
33
|
+
self.real_data_end_address = None
|
34
|
+
try:
|
35
|
+
point_config = InverterConfig(**point_config)
|
36
|
+
except Validator as e:
|
37
|
+
print(e)
|
38
|
+
for index, real_point in enumerate(point_config.real_data):
|
39
|
+
point_key = real_point.point_key
|
40
|
+
point_id = real_point.point_id
|
41
|
+
self.col_name_index_map[point_key] = real_point
|
42
|
+
self.col_index_name_map[point_id] = real_point
|
43
|
+
self.col_id_index_map[point_id] = index
|
44
|
+
self.real_data_start_address = min(
|
45
|
+
self.real_data_start_address, real_point.starting_address
|
46
|
+
)
|
47
|
+
self.real_data_end_address = max(
|
48
|
+
self.real_data_end_address,
|
49
|
+
real_point.starting_address + real_point.quantity_of_x - 1,
|
50
|
+
)
|
51
|
+
|
52
|
+
self.sn_config = point_config.other_data.sn
|
53
|
+
self.shutdown_config = point_config.other_data.shutdown
|
54
|
+
self.boot_up_config = point_config.other_data.boot_up
|
55
|
+
self.time_config = point_config.other_data.time
|
56
|
+
self.version_config = point_config.other_data.version
|
57
|
+
|
58
|
+
self.error_map = point_config.error_map
|
59
|
+
|
60
|
+
def read_real_data(self, modbus_client, slave):
|
61
|
+
real_data = self._execute_modbus(
|
62
|
+
modbus_client,
|
63
|
+
slave,
|
64
|
+
ReadModbusPoint(
|
65
|
+
starting_address=self.real_data_start_address,
|
66
|
+
quantity_of_x=self.real_data_end_address
|
67
|
+
- self.real_data_start_address
|
68
|
+
+ 1,
|
69
|
+
function_code=InverterPoint.function_code,
|
70
|
+
),
|
71
|
+
)
|
72
|
+
ret_real_data = {}
|
73
|
+
for point_id, point_info in self.col_index_name_map.items():
|
74
|
+
offset = point_info.starting_address
|
75
|
+
data = real_data[offset : offset + point_info.quantity_of_x]
|
76
|
+
ret_real_data[point_id] = self._parse_point_data(point_info, data)
|
77
|
+
return ret_real_data
|
78
|
+
|
79
|
+
def read_real_data_to_list(self, modbus_client, slave):
|
80
|
+
real_data = self.read_real_data(modbus_client, slave)
|
81
|
+
return list(real_data.values())
|
82
|
+
|
83
|
+
def _parse_point_data(self, point_info: InverterPoint, point_data):
|
84
|
+
value = unpack(
|
85
|
+
point_data, data_format=point_info.register_dataformat, reversed=True
|
86
|
+
)
|
87
|
+
accuracy = point_info.accuracy
|
88
|
+
return round_value(value * accuracy, 3)
|
89
|
+
|
90
|
+
def get_data_by_point_id_from_list(self, point_id, real_data):
|
91
|
+
point_index = self.col_id_index_map[point_id]
|
92
|
+
return real_data[point_index]
|
93
|
+
|
94
|
+
@abstractmethod
|
95
|
+
def get_real_power(self, read_data):
|
96
|
+
raise NotImplementedError()
|
97
|
+
|
98
|
+
@abstractmethod
|
99
|
+
def get_error_data(self, read_data):
|
100
|
+
raise NotImplementedError()
|
101
|
+
|
102
|
+
@abstractmethod
|
103
|
+
def parse_pcs_status(self, read_data):
|
104
|
+
...
|
105
|
+
|
106
|
+
@abstractmethod
|
107
|
+
def parse_error_code(self, error_data):
|
108
|
+
...
|
109
|
+
|
110
|
+
def error_to_alarm_code(self, error_codes: List[int]):
|
111
|
+
if not self.error_map:
|
112
|
+
return error_codes
|
113
|
+
alarm_codes = []
|
114
|
+
for error_code in error_codes:
|
115
|
+
if alarm_code := self.error_map.get(error_code):
|
116
|
+
alarm_codes.append(alarm_code)
|
117
|
+
return alarm_codes
|
118
|
+
|
119
|
+
def pv_power_data(self, real_data):
|
120
|
+
...
|
121
|
+
|
122
|
+
def get_pv_capacity(self, real_data, history_data):
|
123
|
+
...
|
124
|
+
|
125
|
+
def get_active_power(self, read_data):
|
126
|
+
...
|
127
|
+
|
128
|
+
def get_reactive_power(self, read_data):
|
129
|
+
...
|
130
|
+
|
131
|
+
# ============================== read or write =========================================
|
132
|
+
|
133
|
+
def _execute_modbus(
|
134
|
+
self,
|
135
|
+
modbus_client,
|
136
|
+
slave_num,
|
137
|
+
point_info: Union[WriteModbusPoint, ReadModbusPoint],
|
138
|
+
output_value=None,
|
139
|
+
):
|
140
|
+
try:
|
141
|
+
ret = modbus_client.read_and_write(
|
142
|
+
slave_num,
|
143
|
+
**point_info.dict(
|
144
|
+
include={"starting_address", "quantity_of_x", "function_code"}
|
145
|
+
),
|
146
|
+
output_value=output_value,
|
147
|
+
)
|
148
|
+
except Exception as e:
|
149
|
+
print(e)
|
150
|
+
return ret
|
151
|
+
|
152
|
+
def shutdown(self, modbus_client, slave_num):
|
153
|
+
self._execute_modbus(
|
154
|
+
modbus_client,
|
155
|
+
slave_num,
|
156
|
+
self.shutdown_config,
|
157
|
+
output_value=self.shutdown_config.output_value,
|
158
|
+
)
|
159
|
+
|
160
|
+
def boot_up(self, modbus_client, slave_num):
|
161
|
+
self._execute_modbus(
|
162
|
+
modbus_client,
|
163
|
+
slave_num,
|
164
|
+
self.boot_up_config,
|
165
|
+
output_value=self.boot_up_config.output_value,
|
166
|
+
)
|
167
|
+
|
168
|
+
def read_sn(self, modbus_client, slave_num):
|
169
|
+
return self._execute_modbus(modbus_client, slave_num, self.sn_config)
|
170
|
+
|
171
|
+
def read_soft_version_and_hard_version(self, modbus_client, slave_num):
|
172
|
+
soft_inv_version = self.read_soft_version(modbus_client, slave_num)
|
173
|
+
hard_inv_version = self.read_hard_version(modbus_client, slave_num)
|
174
|
+
return soft_inv_version, hard_inv_version
|
175
|
+
|
176
|
+
def read_soft_version(self, modbus_client, slave_num):
|
177
|
+
return self._execute_modbus(
|
178
|
+
modbus_client, slave_num, self.version_config.software
|
179
|
+
)
|
180
|
+
|
181
|
+
def read_hard_version(self, modbus_client, slave_num):
|
182
|
+
return self._execute_modbus(
|
183
|
+
modbus_client, slave_num, self.version_config.hardware
|
184
|
+
)
|
185
|
+
|
186
|
+
def get_upgrade_value(self, crc, file_size):
|
187
|
+
crc_nums = [crc[1], crc[0]]
|
188
|
+
file_size = [file_size[1], file_size[0]]
|
189
|
+
value = (
|
190
|
+
[self.inverter_model]
|
191
|
+
+ crc_nums
|
192
|
+
+ [1, 0, 0, 0, 0, 0, 0]
|
193
|
+
+ file_size
|
194
|
+
+ [1, 0, 0]
|
195
|
+
)
|
196
|
+
return value
|
197
|
+
|
198
|
+
def write_pcs_time(self, modbus_client, slave_num):
|
199
|
+
self._execute_modbus(
|
200
|
+
modbus_client,
|
201
|
+
slave_num,
|
202
|
+
self.time_config,
|
203
|
+
output_value=self._build_pcs_time_value(),
|
204
|
+
)
|
205
|
+
|
206
|
+
def _build_pcs_time_value(self):
|
207
|
+
cur_time = datetime.now()
|
208
|
+
return [
|
209
|
+
cur_time.year,
|
210
|
+
cur_time.month,
|
211
|
+
cur_time.day,
|
212
|
+
cur_time.hour,
|
213
|
+
cur_time.minute,
|
214
|
+
cur_time.second,
|
215
|
+
]
|
@@ -1,41 +1,41 @@
|
|
1
|
-
from typing import List, Optional, Dict
|
2
|
-
from modbus_tk import defines
|
3
|
-
|
4
|
-
from pydantic import BaseModel
|
5
|
-
from enum import IntEnum
|
6
|
-
|
7
|
-
from solax_py_library.device.types.modbus_point import ReadModbusPoint, WriteModbusPoint
|
8
|
-
|
9
|
-
|
10
|
-
class InverterModel(IntEnum):
|
11
|
-
...
|
12
|
-
|
13
|
-
def __str__(self):
|
14
|
-
...
|
15
|
-
|
16
|
-
|
17
|
-
class InverterPoint(ReadModbusPoint):
|
18
|
-
description: Optional[str]
|
19
|
-
point_key: str
|
20
|
-
point_id: int
|
21
|
-
accuracy: Optional[float]
|
22
|
-
function_code: int = defines.READ_INPUT_REGISTERS
|
23
|
-
|
24
|
-
|
25
|
-
class InverterVersionConfig(BaseModel):
|
26
|
-
software: ReadModbusPoint
|
27
|
-
hardware: ReadModbusPoint
|
28
|
-
|
29
|
-
|
30
|
-
class InverterSystemConfig(BaseModel):
|
31
|
-
sn: ReadModbusPoint
|
32
|
-
shutdown: WriteModbusPoint
|
33
|
-
boot_up: WriteModbusPoint
|
34
|
-
time: WriteModbusPoint
|
35
|
-
version: InverterVersionConfig
|
36
|
-
|
37
|
-
|
38
|
-
class InverterConfig(BaseModel):
|
39
|
-
real_data: List[InverterPoint]
|
40
|
-
other_data: InverterSystemConfig
|
41
|
-
error_map: Dict[int, int]
|
1
|
+
from typing import List, Optional, Dict
|
2
|
+
from modbus_tk import defines
|
3
|
+
|
4
|
+
from pydantic import BaseModel
|
5
|
+
from enum import IntEnum
|
6
|
+
|
7
|
+
from solax_py_library.device.types.modbus_point import ReadModbusPoint, WriteModbusPoint
|
8
|
+
|
9
|
+
|
10
|
+
class InverterModel(IntEnum):
|
11
|
+
...
|
12
|
+
|
13
|
+
def __str__(self):
|
14
|
+
...
|
15
|
+
|
16
|
+
|
17
|
+
class InverterPoint(ReadModbusPoint):
|
18
|
+
description: Optional[str]
|
19
|
+
point_key: str
|
20
|
+
point_id: int
|
21
|
+
accuracy: Optional[float]
|
22
|
+
function_code: int = defines.READ_INPUT_REGISTERS
|
23
|
+
|
24
|
+
|
25
|
+
class InverterVersionConfig(BaseModel):
|
26
|
+
software: ReadModbusPoint
|
27
|
+
hardware: ReadModbusPoint
|
28
|
+
|
29
|
+
|
30
|
+
class InverterSystemConfig(BaseModel):
|
31
|
+
sn: ReadModbusPoint
|
32
|
+
shutdown: WriteModbusPoint
|
33
|
+
boot_up: WriteModbusPoint
|
34
|
+
time: WriteModbusPoint
|
35
|
+
version: InverterVersionConfig
|
36
|
+
|
37
|
+
|
38
|
+
class InverterConfig(BaseModel):
|
39
|
+
real_data: List[InverterPoint]
|
40
|
+
other_data: InverterSystemConfig
|
41
|
+
error_map: Dict[int, int]
|
@@ -1,30 +1,30 @@
|
|
1
|
-
from typing import Union, List
|
2
|
-
|
3
|
-
from pydantic import BaseModel
|
4
|
-
from enum import StrEnum
|
5
|
-
|
6
|
-
|
7
|
-
class ModbusPoint(BaseModel):
|
8
|
-
starting_address: int
|
9
|
-
quantity_of_x: int
|
10
|
-
function_code: int
|
11
|
-
|
12
|
-
|
13
|
-
class RegisterDataformat(StrEnum):
|
14
|
-
int8 = "int8"
|
15
|
-
uint8 = "uint8"
|
16
|
-
int16 = "int16"
|
17
|
-
uint16 = "uint16"
|
18
|
-
int32 = "int32"
|
19
|
-
uint32 = "uint32"
|
20
|
-
int64 = "int64"
|
21
|
-
uint64 = "uint64"
|
22
|
-
float = "float"
|
23
|
-
|
24
|
-
|
25
|
-
class ReadModbusPoint(ModbusPoint):
|
26
|
-
register_dataformat: RegisterDataformat
|
27
|
-
|
28
|
-
|
29
|
-
class WriteModbusPoint(ModbusPoint):
|
30
|
-
output_value: Union[int, List[int], None]
|
1
|
+
from typing import Union, List
|
2
|
+
|
3
|
+
from pydantic import BaseModel
|
4
|
+
from enum import StrEnum
|
5
|
+
|
6
|
+
|
7
|
+
class ModbusPoint(BaseModel):
|
8
|
+
starting_address: int
|
9
|
+
quantity_of_x: int
|
10
|
+
function_code: int
|
11
|
+
|
12
|
+
|
13
|
+
class RegisterDataformat(StrEnum):
|
14
|
+
int8 = "int8"
|
15
|
+
uint8 = "uint8"
|
16
|
+
int16 = "int16"
|
17
|
+
uint16 = "uint16"
|
18
|
+
int32 = "int32"
|
19
|
+
uint32 = "uint32"
|
20
|
+
int64 = "int64"
|
21
|
+
uint64 = "uint64"
|
22
|
+
float = "float"
|
23
|
+
|
24
|
+
|
25
|
+
class ReadModbusPoint(ModbusPoint):
|
26
|
+
register_dataformat: RegisterDataformat
|
27
|
+
|
28
|
+
|
29
|
+
class WriteModbusPoint(ModbusPoint):
|
30
|
+
output_value: Union[int, List[int], None]
|
solax_py_library/exception.py
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
class SolaxBaseError(Exception):
|
2
|
-
code = 0x1000
|
3
|
-
message = "upload error"
|
4
|
-
|
5
|
-
def __init__(self, *args, message=None):
|
6
|
-
super().__init__(*args)
|
7
|
-
self.message = message or self.message
|
8
|
-
|
9
|
-
def __str__(self):
|
10
|
-
return self.message
|
1
|
+
class SolaxBaseError(Exception):
|
2
|
+
code = 0x1000
|
3
|
+
message = "upload error"
|
4
|
+
|
5
|
+
def __init__(self, *args, message=None):
|
6
|
+
super().__init__(*args)
|
7
|
+
self.message = message or self.message
|
8
|
+
|
9
|
+
def __str__(self):
|
10
|
+
return self.message
|
File without changes
|
File without changes
|