solax-py-library 1.0.0.19__py3-none-any.whl → 1.0.0.21__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/__init__.py +0 -0
- solax_py_library/device/constant/__init__.py +0 -0
- solax_py_library/device/constant/inverter_model_info.py +312 -0
- solax_py_library/device/core/__init__.py +0 -0
- solax_py_library/device/core/interver/__init__.py +36 -0
- solax_py_library/device/core/interver/base.py +215 -0
- solax_py_library/device/types/__init__.py +0 -0
- solax_py_library/device/types/inverter_config.py +41 -0
- solax_py_library/device/types/modbus_point.py +30 -0
- solax_py_library/exception.py +10 -10
- 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 +2 -2
- solax_py_library/snap_shot/core/base_modbus.py +14 -14
- solax_py_library/snap_shot/core/parser.py +225 -225
- solax_py_library/snap_shot/core/snap_shot.py +14 -12
- 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/upload/__init__.py +3 -3
- solax_py_library/upload/api/service.py +24 -24
- solax_py_library/upload/core/upload_service/ftp.py +2 -2
- solax_py_library/upload/exceptions/__init__.py +8 -10
- solax_py_library/upload/exceptions/upload_error.py +21 -21
- solax_py_library/upload/test/test_ftp.py +1 -1
- solax_py_library/utils/common.py +21 -2
- solax_py_library/utils/struct_util.py +30 -0
- {solax_py_library-1.0.0.19.dist-info → solax_py_library-1.0.0.21.dist-info}/METADATA +1 -1
- solax_py_library-1.0.0.21.dist-info/RECORD +46 -0
- solax_py_library-1.0.0.19.dist-info/RECORD +0 -36
- {solax_py_library-1.0.0.19.dist-info → solax_py_library-1.0.0.21.dist-info}/WHEEL +0 -0
@@ -1,225 +1,225 @@
|
|
1
|
-
import re
|
2
|
-
import struct
|
3
|
-
|
4
|
-
from solax_py_library.snap_shot.types.address import CommandType
|
5
|
-
from solax_py_library.snap_shot.constant.crc_table import CRC_Table
|
6
|
-
|
7
|
-
|
8
|
-
class Parser:
|
9
|
-
def parse(self, char16):
|
10
|
-
"""
|
11
|
-
:return:
|
12
|
-
"""
|
13
|
-
task_id = self.ascii_to_str(char16[12:76]) # task_id
|
14
|
-
device_type = int(char16[76:78]) # 设备类型
|
15
|
-
device_sn = self.ascii_to_str(char16[78:118]) # 设备SN
|
16
|
-
business_type = int(char16[118:120])
|
17
|
-
data = char16[120:]
|
18
|
-
return {
|
19
|
-
"task_id": task_id,
|
20
|
-
"sn": device_sn,
|
21
|
-
"device_type": device_type,
|
22
|
-
"business_type": business_type,
|
23
|
-
"message": char16,
|
24
|
-
"data": data,
|
25
|
-
}
|
26
|
-
|
27
|
-
def ascii_to_str(self, data: str):
|
28
|
-
"""阿斯科码转字符串"""
|
29
|
-
pattern = re.compile(".{2}")
|
30
|
-
message = "\\u00" + "\\u00".join(pattern.findall(data))
|
31
|
-
message = message.replace("\\u0000", "")
|
32
|
-
message = bytes(message, encoding="utf-8").decode("unicode-escape")
|
33
|
-
return message
|
34
|
-
|
35
|
-
def upload_data(self, big_data: bytes, task_id: str, upload_data):
|
36
|
-
business_type = 1 # 1 代表调试信息
|
37
|
-
data_type = 0 # 0代表故障录波
|
38
|
-
|
39
|
-
# 分片上传(每包1K)
|
40
|
-
chunk_size = 1024
|
41
|
-
total_chunks = (len(big_data) + chunk_size - 1) // chunk_size
|
42
|
-
|
43
|
-
# 遍历分片并构造数据包
|
44
|
-
for chunk_idx, chunk_data in self.data_chunk_generator(big_data, chunk_size):
|
45
|
-
frame = self.build_data_packet_frame(
|
46
|
-
task_id=task_id,
|
47
|
-
business_type=business_type,
|
48
|
-
data_type=data_type,
|
49
|
-
total_packets=total_chunks,
|
50
|
-
current_packet=chunk_idx,
|
51
|
-
chunk_data=chunk_data,
|
52
|
-
)
|
53
|
-
|
54
|
-
print(f"发送包 {chunk_idx + 1}/{total_chunks}, 长度={len(frame)} 字节")
|
55
|
-
upload_data(frame)
|
56
|
-
|
57
|
-
def data_chunk_generator(self, data: bytes, chunk_size: int = 1024):
|
58
|
-
"""
|
59
|
-
将大数据按固定包大小分片
|
60
|
-
:param data: 原始数据字节流
|
61
|
-
:param chunk_size: 每包最大字节数(默认1024)
|
62
|
-
:yield: (当前包序号, 分片数据)
|
63
|
-
"""
|
64
|
-
total = len(data)
|
65
|
-
if total == 0:
|
66
|
-
yield (0, b"") # 空数据单独处理
|
67
|
-
return
|
68
|
-
|
69
|
-
total_chunks = (total + chunk_size - 1) // chunk_size
|
70
|
-
|
71
|
-
for i in range(total_chunks):
|
72
|
-
start = i * chunk_size
|
73
|
-
end = start + chunk_size
|
74
|
-
yield (i, data[start:end])
|
75
|
-
|
76
|
-
def build_response_frame(
|
77
|
-
self, task_id: str, business_type: int, ack_code: int
|
78
|
-
) -> bytes:
|
79
|
-
"""
|
80
|
-
构建接收应答帧(指令类型 0x80)
|
81
|
-
:param task_id: 任务ID(32字节)
|
82
|
-
:param business_type: 业务类型(0或1)
|
83
|
-
:param ack_code: 0-成功,1-失败,2-执行中
|
84
|
-
"""
|
85
|
-
# 固定字段
|
86
|
-
header = bytes([0x24, 0x24])
|
87
|
-
func_code = bytes([0x05, 0x07]) # 主功能码5 + 子功能码7
|
88
|
-
|
89
|
-
# 数据域
|
90
|
-
task_bytes = task_id.encode("ascii")[:32].ljust(32, b"\x00")
|
91
|
-
business_byte = bytes([business_type])
|
92
|
-
cmd_byte = bytes([CommandType.ACK.value])
|
93
|
-
ack_byte = bytes([ack_code])
|
94
|
-
data_part = task_bytes + business_byte + cmd_byte + ack_byte
|
95
|
-
|
96
|
-
# 计算长度(功能码2字节 + 数据域37字节 + CRC2字节 = 41)
|
97
|
-
frame_length = len(func_code) + len(data_part) + 2
|
98
|
-
length_bytes = struct.pack("<H", frame_length)
|
99
|
-
|
100
|
-
# 构建临时帧并计算CRC
|
101
|
-
temp_frame = header + length_bytes + func_code + data_part
|
102
|
-
crc = self.crc(temp_frame.hex()).upper()
|
103
|
-
full_frame = temp_frame + bytes.fromhex(crc)
|
104
|
-
return full_frame
|
105
|
-
|
106
|
-
def build_total_packets_frame(
|
107
|
-
self, task_id: str, business_type: int, data_type: int, total_packets: int
|
108
|
-
) -> bytes:
|
109
|
-
"""
|
110
|
-
构建上报总包数帧(指令类型 0x81)
|
111
|
-
:param total_packets: 总包数(若为0,平台停止接收)
|
112
|
-
"""
|
113
|
-
header = bytes([0x24, 0x24])
|
114
|
-
func_code = bytes([0x05, 0x07])
|
115
|
-
|
116
|
-
# 数据域
|
117
|
-
task_bytes = task_id.encode("ascii")[:32].ljust(32, b"\x00")
|
118
|
-
business_byte = bytes([business_type])
|
119
|
-
cmd_byte = bytes([CommandType.TOTAL_PACKETS.value])
|
120
|
-
data_length = struct.pack("<H", 2) # 数据长度固定2字节
|
121
|
-
data_type_byte = bytes([data_type])
|
122
|
-
total_packets_bytes = struct.pack("<H", total_packets)
|
123
|
-
|
124
|
-
data_part = (
|
125
|
-
task_bytes
|
126
|
-
+ business_byte
|
127
|
-
+ cmd_byte
|
128
|
-
+ data_length
|
129
|
-
+ data_type_byte
|
130
|
-
+ total_packets_bytes
|
131
|
-
)
|
132
|
-
|
133
|
-
# 计算长度
|
134
|
-
frame_length = len(func_code) + len(data_part) + 2
|
135
|
-
length_bytes = struct.pack("<H", frame_length)
|
136
|
-
|
137
|
-
# 附加CRC
|
138
|
-
temp_frame = header + length_bytes + func_code + data_part
|
139
|
-
crc = self.crc(temp_frame.hex()).upper()
|
140
|
-
return temp_frame + bytes.fromhex(crc)
|
141
|
-
|
142
|
-
def build_data_packet_frame(
|
143
|
-
self,
|
144
|
-
task_id: str,
|
145
|
-
business_type: int,
|
146
|
-
data_type: int,
|
147
|
-
total_packets: int,
|
148
|
-
current_packet: int,
|
149
|
-
chunk_data: bytes,
|
150
|
-
) -> bytes:
|
151
|
-
"""
|
152
|
-
构建具体分包数据帧(指令类型 0x82)
|
153
|
-
"""
|
154
|
-
header = bytes([0x24, 0x24])
|
155
|
-
func_code = bytes([0x05, 0x07])
|
156
|
-
|
157
|
-
# 数据域
|
158
|
-
task_bytes = task_id.encode("ascii")[:32].ljust(32, b"\x00")
|
159
|
-
business_byte = bytes([business_type])
|
160
|
-
cmd_byte = bytes([CommandType.DATA_PACKET.value])
|
161
|
-
data_type_byte = bytes([data_type])
|
162
|
-
total_packets_bytes = struct.pack("<H", total_packets)
|
163
|
-
current_packet_bytes = struct.pack("<H", current_packet)
|
164
|
-
data_length = struct.pack("<H", len(chunk_data))
|
165
|
-
|
166
|
-
data_part = (
|
167
|
-
task_bytes
|
168
|
-
+ business_byte
|
169
|
-
+ cmd_byte
|
170
|
-
+ data_type_byte
|
171
|
-
+ total_packets_bytes
|
172
|
-
+ current_packet_bytes
|
173
|
-
+ data_length
|
174
|
-
+ chunk_data
|
175
|
-
)
|
176
|
-
|
177
|
-
# 计算长度
|
178
|
-
frame_length = len(func_code) + len(data_part) + 2
|
179
|
-
length_bytes = struct.pack("<H", frame_length)
|
180
|
-
|
181
|
-
# 附加CRC
|
182
|
-
temp_frame = header + length_bytes + func_code + data_part
|
183
|
-
crc = self.crc(temp_frame.hex()).upper()
|
184
|
-
return temp_frame + bytes.fromhex(crc)
|
185
|
-
|
186
|
-
def build_error_frame(
|
187
|
-
self, task_id: str, business_type: int, error_type: int
|
188
|
-
) -> bytes:
|
189
|
-
"""
|
190
|
-
构建报错应答帧(指令类型 0x83)
|
191
|
-
|
192
|
-
"""
|
193
|
-
header = bytes([0x24, 0x24])
|
194
|
-
func_code = bytes([0x05, 0x07])
|
195
|
-
|
196
|
-
# 数据域
|
197
|
-
task_bytes = task_id.encode("ascii")[:32].ljust(32, b"\x00")
|
198
|
-
business_byte = bytes([business_type])
|
199
|
-
cmd_byte = bytes([CommandType.ERROR.value])
|
200
|
-
error_byte = bytes([error_type])
|
201
|
-
data_part = task_bytes + business_byte + cmd_byte + error_byte
|
202
|
-
|
203
|
-
# 计算长度
|
204
|
-
frame_length = len(func_code) + len(data_part) + 2
|
205
|
-
length_bytes = struct.pack("<H", frame_length)
|
206
|
-
|
207
|
-
# 附加CRC
|
208
|
-
temp_frame = header + length_bytes + func_code + data_part
|
209
|
-
crc = self.crc(temp_frame.hex()).upper()
|
210
|
-
return temp_frame + bytes.fromhex(crc)
|
211
|
-
|
212
|
-
def crc(self, message):
|
213
|
-
"""获取校验位, message: 除去校验位"""
|
214
|
-
crc = 0
|
215
|
-
i = 0
|
216
|
-
length = len(message) // 2
|
217
|
-
while length > 0:
|
218
|
-
crc &= 0xFFFFFFFF
|
219
|
-
da = crc // 256
|
220
|
-
da &= 0xFF
|
221
|
-
crc <<= 8
|
222
|
-
crc ^= CRC_Table[da ^ int(message[i : i + 2], 16)]
|
223
|
-
i += 2
|
224
|
-
length -= 1
|
225
|
-
return f"{crc & 0xffff:04x}"
|
1
|
+
import re
|
2
|
+
import struct
|
3
|
+
|
4
|
+
from solax_py_library.snap_shot.types.address import CommandType
|
5
|
+
from solax_py_library.snap_shot.constant.crc_table import CRC_Table
|
6
|
+
|
7
|
+
|
8
|
+
class Parser:
|
9
|
+
def parse(self, char16):
|
10
|
+
"""
|
11
|
+
:return:
|
12
|
+
"""
|
13
|
+
task_id = self.ascii_to_str(char16[12:76]) # task_id
|
14
|
+
device_type = int(char16[76:78]) # 设备类型
|
15
|
+
device_sn = self.ascii_to_str(char16[78:118]) # 设备SN
|
16
|
+
business_type = int(char16[118:120])
|
17
|
+
data = char16[120:]
|
18
|
+
return {
|
19
|
+
"task_id": task_id,
|
20
|
+
"sn": device_sn,
|
21
|
+
"device_type": device_type,
|
22
|
+
"business_type": business_type,
|
23
|
+
"message": char16,
|
24
|
+
"data": data,
|
25
|
+
}
|
26
|
+
|
27
|
+
def ascii_to_str(self, data: str):
|
28
|
+
"""阿斯科码转字符串"""
|
29
|
+
pattern = re.compile(".{2}")
|
30
|
+
message = "\\u00" + "\\u00".join(pattern.findall(data))
|
31
|
+
message = message.replace("\\u0000", "")
|
32
|
+
message = bytes(message, encoding="utf-8").decode("unicode-escape")
|
33
|
+
return message
|
34
|
+
|
35
|
+
def upload_data(self, big_data: bytes, task_id: str, upload_data):
|
36
|
+
business_type = 1 # 1 代表调试信息
|
37
|
+
data_type = 0 # 0代表故障录波
|
38
|
+
|
39
|
+
# 分片上传(每包1K)
|
40
|
+
chunk_size = 1024
|
41
|
+
total_chunks = (len(big_data) + chunk_size - 1) // chunk_size
|
42
|
+
|
43
|
+
# 遍历分片并构造数据包
|
44
|
+
for chunk_idx, chunk_data in self.data_chunk_generator(big_data, chunk_size):
|
45
|
+
frame = self.build_data_packet_frame(
|
46
|
+
task_id=task_id,
|
47
|
+
business_type=business_type,
|
48
|
+
data_type=data_type,
|
49
|
+
total_packets=total_chunks,
|
50
|
+
current_packet=chunk_idx,
|
51
|
+
chunk_data=chunk_data,
|
52
|
+
)
|
53
|
+
|
54
|
+
print(f"发送包 {chunk_idx + 1}/{total_chunks}, 长度={len(frame)} 字节")
|
55
|
+
upload_data(frame)
|
56
|
+
|
57
|
+
def data_chunk_generator(self, data: bytes, chunk_size: int = 1024):
|
58
|
+
"""
|
59
|
+
将大数据按固定包大小分片
|
60
|
+
:param data: 原始数据字节流
|
61
|
+
:param chunk_size: 每包最大字节数(默认1024)
|
62
|
+
:yield: (当前包序号, 分片数据)
|
63
|
+
"""
|
64
|
+
total = len(data)
|
65
|
+
if total == 0:
|
66
|
+
yield (0, b"") # 空数据单独处理
|
67
|
+
return
|
68
|
+
|
69
|
+
total_chunks = (total + chunk_size - 1) // chunk_size
|
70
|
+
|
71
|
+
for i in range(total_chunks):
|
72
|
+
start = i * chunk_size
|
73
|
+
end = start + chunk_size
|
74
|
+
yield (i, data[start:end])
|
75
|
+
|
76
|
+
def build_response_frame(
|
77
|
+
self, task_id: str, business_type: int, ack_code: int
|
78
|
+
) -> bytes:
|
79
|
+
"""
|
80
|
+
构建接收应答帧(指令类型 0x80)
|
81
|
+
:param task_id: 任务ID(32字节)
|
82
|
+
:param business_type: 业务类型(0或1)
|
83
|
+
:param ack_code: 0-成功,1-失败,2-执行中
|
84
|
+
"""
|
85
|
+
# 固定字段
|
86
|
+
header = bytes([0x24, 0x24])
|
87
|
+
func_code = bytes([0x05, 0x07]) # 主功能码5 + 子功能码7
|
88
|
+
|
89
|
+
# 数据域
|
90
|
+
task_bytes = task_id.encode("ascii")[:32].ljust(32, b"\x00")
|
91
|
+
business_byte = bytes([business_type])
|
92
|
+
cmd_byte = bytes([CommandType.ACK.value])
|
93
|
+
ack_byte = bytes([ack_code])
|
94
|
+
data_part = task_bytes + business_byte + cmd_byte + ack_byte
|
95
|
+
|
96
|
+
# 计算长度(功能码2字节 + 数据域37字节 + CRC2字节 = 41)
|
97
|
+
frame_length = len(func_code) + len(data_part) + 2
|
98
|
+
length_bytes = struct.pack("<H", frame_length)
|
99
|
+
|
100
|
+
# 构建临时帧并计算CRC
|
101
|
+
temp_frame = header + length_bytes + func_code + data_part
|
102
|
+
crc = self.crc(temp_frame.hex()).upper()
|
103
|
+
full_frame = temp_frame + bytes.fromhex(crc)
|
104
|
+
return full_frame
|
105
|
+
|
106
|
+
def build_total_packets_frame(
|
107
|
+
self, task_id: str, business_type: int, data_type: int, total_packets: int
|
108
|
+
) -> bytes:
|
109
|
+
"""
|
110
|
+
构建上报总包数帧(指令类型 0x81)
|
111
|
+
:param total_packets: 总包数(若为0,平台停止接收)
|
112
|
+
"""
|
113
|
+
header = bytes([0x24, 0x24])
|
114
|
+
func_code = bytes([0x05, 0x07])
|
115
|
+
|
116
|
+
# 数据域
|
117
|
+
task_bytes = task_id.encode("ascii")[:32].ljust(32, b"\x00")
|
118
|
+
business_byte = bytes([business_type])
|
119
|
+
cmd_byte = bytes([CommandType.TOTAL_PACKETS.value])
|
120
|
+
data_length = struct.pack("<H", 2) # 数据长度固定2字节
|
121
|
+
data_type_byte = bytes([data_type])
|
122
|
+
total_packets_bytes = struct.pack("<H", total_packets)
|
123
|
+
|
124
|
+
data_part = (
|
125
|
+
task_bytes
|
126
|
+
+ business_byte
|
127
|
+
+ cmd_byte
|
128
|
+
+ data_length
|
129
|
+
+ data_type_byte
|
130
|
+
+ total_packets_bytes
|
131
|
+
)
|
132
|
+
|
133
|
+
# 计算长度
|
134
|
+
frame_length = len(func_code) + len(data_part) + 2
|
135
|
+
length_bytes = struct.pack("<H", frame_length)
|
136
|
+
|
137
|
+
# 附加CRC
|
138
|
+
temp_frame = header + length_bytes + func_code + data_part
|
139
|
+
crc = self.crc(temp_frame.hex()).upper()
|
140
|
+
return temp_frame + bytes.fromhex(crc)
|
141
|
+
|
142
|
+
def build_data_packet_frame(
|
143
|
+
self,
|
144
|
+
task_id: str,
|
145
|
+
business_type: int,
|
146
|
+
data_type: int,
|
147
|
+
total_packets: int,
|
148
|
+
current_packet: int,
|
149
|
+
chunk_data: bytes,
|
150
|
+
) -> bytes:
|
151
|
+
"""
|
152
|
+
构建具体分包数据帧(指令类型 0x82)
|
153
|
+
"""
|
154
|
+
header = bytes([0x24, 0x24])
|
155
|
+
func_code = bytes([0x05, 0x07])
|
156
|
+
|
157
|
+
# 数据域
|
158
|
+
task_bytes = task_id.encode("ascii")[:32].ljust(32, b"\x00")
|
159
|
+
business_byte = bytes([business_type])
|
160
|
+
cmd_byte = bytes([CommandType.DATA_PACKET.value])
|
161
|
+
data_type_byte = bytes([data_type])
|
162
|
+
total_packets_bytes = struct.pack("<H", total_packets)
|
163
|
+
current_packet_bytes = struct.pack("<H", current_packet)
|
164
|
+
data_length = struct.pack("<H", len(chunk_data))
|
165
|
+
|
166
|
+
data_part = (
|
167
|
+
task_bytes
|
168
|
+
+ business_byte
|
169
|
+
+ cmd_byte
|
170
|
+
+ data_type_byte
|
171
|
+
+ total_packets_bytes
|
172
|
+
+ current_packet_bytes
|
173
|
+
+ data_length
|
174
|
+
+ chunk_data
|
175
|
+
)
|
176
|
+
|
177
|
+
# 计算长度
|
178
|
+
frame_length = len(func_code) + len(data_part) + 2
|
179
|
+
length_bytes = struct.pack("<H", frame_length)
|
180
|
+
|
181
|
+
# 附加CRC
|
182
|
+
temp_frame = header + length_bytes + func_code + data_part
|
183
|
+
crc = self.crc(temp_frame.hex()).upper()
|
184
|
+
return temp_frame + bytes.fromhex(crc)
|
185
|
+
|
186
|
+
def build_error_frame(
|
187
|
+
self, task_id: str, business_type: int, error_type: int
|
188
|
+
) -> bytes:
|
189
|
+
"""
|
190
|
+
构建报错应答帧(指令类型 0x83)
|
191
|
+
|
192
|
+
"""
|
193
|
+
header = bytes([0x24, 0x24])
|
194
|
+
func_code = bytes([0x05, 0x07])
|
195
|
+
|
196
|
+
# 数据域
|
197
|
+
task_bytes = task_id.encode("ascii")[:32].ljust(32, b"\x00")
|
198
|
+
business_byte = bytes([business_type])
|
199
|
+
cmd_byte = bytes([CommandType.ERROR.value])
|
200
|
+
error_byte = bytes([error_type])
|
201
|
+
data_part = task_bytes + business_byte + cmd_byte + error_byte
|
202
|
+
|
203
|
+
# 计算长度
|
204
|
+
frame_length = len(func_code) + len(data_part) + 2
|
205
|
+
length_bytes = struct.pack("<H", frame_length)
|
206
|
+
|
207
|
+
# 附加CRC
|
208
|
+
temp_frame = header + length_bytes + func_code + data_part
|
209
|
+
crc = self.crc(temp_frame.hex()).upper()
|
210
|
+
return temp_frame + bytes.fromhex(crc)
|
211
|
+
|
212
|
+
def crc(self, message):
|
213
|
+
"""获取校验位, message: 除去校验位"""
|
214
|
+
crc = 0
|
215
|
+
i = 0
|
216
|
+
length = len(message) // 2
|
217
|
+
while length > 0:
|
218
|
+
crc &= 0xFFFFFFFF
|
219
|
+
da = crc // 256
|
220
|
+
da &= 0xFF
|
221
|
+
crc <<= 8
|
222
|
+
crc ^= CRC_Table[da ^ int(message[i : i + 2], 16)]
|
223
|
+
i += 2
|
224
|
+
length -= 1
|
225
|
+
return f"{crc & 0xffff:04x}"
|
@@ -1,6 +1,8 @@
|
|
1
1
|
from typing import Dict, Optional, List
|
2
2
|
import asyncio
|
3
3
|
|
4
|
+
from solax_py_library.snap_shot.exceptions import SnapshotTimeoutError
|
5
|
+
|
4
6
|
from solax_py_library.snap_shot.core.base_modbus import ModbusClientBase
|
5
7
|
from solax_py_library.snap_shot.types.address import *
|
6
8
|
from solax_py_library.utils.common import retry
|
@@ -23,7 +25,7 @@ class SnapshotCore:
|
|
23
25
|
def all_snap_data(self):
|
24
26
|
return self.all_snap_shot_data.copy()
|
25
27
|
|
26
|
-
@retry(max_attempts=3, delay=0.5)
|
28
|
+
@retry(max_attempts=3, delay=0.5, assign_exception=SnapshotTimeoutError)
|
27
29
|
async def _set_MCU_source(self):
|
28
30
|
print("step 1 设置芯片源")
|
29
31
|
result = await self.modbus.write_registers(
|
@@ -32,7 +34,7 @@ class SnapshotCore:
|
|
32
34
|
)
|
33
35
|
print(f"step 1 设置芯片源回复:0x{result[0]:04x}")
|
34
36
|
|
35
|
-
@retry(max_attempts=3, delay=0.5)
|
37
|
+
@retry(max_attempts=3, delay=0.5, assign_exception=SnapshotTimeoutError)
|
36
38
|
async def _set_export_device(self): # 设置输出设备
|
37
39
|
print("setp 2 设置导出设备")
|
38
40
|
|
@@ -42,7 +44,7 @@ class SnapshotCore:
|
|
42
44
|
)
|
43
45
|
print(f"setp 2 设置导出设备:0x{result[0]:04x}")
|
44
46
|
|
45
|
-
@retry(max_attempts=3, delay=0.5)
|
47
|
+
@retry(max_attempts=3, delay=0.5, assign_exception=SnapshotTimeoutError)
|
46
48
|
async def _get_snapshot_total_number(self) -> int: # 取得快照总数
|
47
49
|
print("step 3 获取快照总数")
|
48
50
|
try_number = 3
|
@@ -58,7 +60,7 @@ class SnapshotCore:
|
|
58
60
|
number += 1
|
59
61
|
return result[0]
|
60
62
|
|
61
|
-
@retry(max_attempts=3, delay=0.5)
|
63
|
+
@retry(max_attempts=3, delay=0.5, assign_exception=SnapshotTimeoutError)
|
62
64
|
async def _start_snap_shot(self): # 获取快照开始结果
|
63
65
|
print("第4步 录播开始")
|
64
66
|
result = False
|
@@ -86,7 +88,7 @@ class SnapshotCore:
|
|
86
88
|
|
87
89
|
return result
|
88
90
|
|
89
|
-
@retry(max_attempts=3, delay=0.5)
|
91
|
+
@retry(max_attempts=3, delay=0.5, assign_exception=SnapshotTimeoutError)
|
90
92
|
async def _get_snapshot_dataPara(
|
91
93
|
self
|
92
94
|
): # 取得快照数据参数 数据总数 通道数 通道数据深度
|
@@ -97,7 +99,7 @@ class SnapshotCore:
|
|
97
99
|
print(f"step 5 获取快照数据参数:{result}")
|
98
100
|
return result[0]
|
99
101
|
|
100
|
-
@retry(max_attempts=3, delay=0.5)
|
102
|
+
@retry(max_attempts=3, delay=0.5, assign_exception=SnapshotTimeoutError)
|
101
103
|
async def _get_Single_snap_shot_data(
|
102
104
|
self, index: int, DataNumber: int
|
103
105
|
): # 获取单个快照数据
|
@@ -127,7 +129,7 @@ class SnapshotCore:
|
|
127
129
|
packindex += 1
|
128
130
|
# print(f'self.all_snap_shot_data:{self.all_snap_shot_data}')
|
129
131
|
|
130
|
-
@retry(max_attempts=3, delay=0.5) #
|
132
|
+
@retry(max_attempts=3, delay=0.5, assign_exception=SnapshotTimeoutError) #
|
131
133
|
async def _set_snap_shot_data_index(self, index: int): # 设置快照数据索引
|
132
134
|
print("step 6 设置快照索引")
|
133
135
|
result = await self.modbus.write_registers(
|
@@ -136,7 +138,7 @@ class SnapshotCore:
|
|
136
138
|
)
|
137
139
|
print(f"step 6 设置快照索引返回值:0x{result[0]:04x}")
|
138
140
|
|
139
|
-
@retry(max_attempts=3, delay=0.5)
|
141
|
+
@retry(max_attempts=3, delay=0.5, assign_exception=SnapshotTimeoutError)
|
140
142
|
async def _get_data_pack_read_state(self): # 取得数据包就绪状态
|
141
143
|
# print(f'取得数据包就绪状态')
|
142
144
|
readcnt = 0
|
@@ -166,7 +168,7 @@ class SnapshotCore:
|
|
166
168
|
# print(f'当前数据包的索引:{packnum}')
|
167
169
|
return packnum
|
168
170
|
|
169
|
-
@retry(max_attempts=3, delay=0.5)
|
171
|
+
@retry(max_attempts=3, delay=0.5, assign_exception=SnapshotTimeoutError)
|
170
172
|
async def _get_data_pack(self, register_num: int) -> List: # 取得快照数据包
|
171
173
|
# print(f'取得快照数据包')
|
172
174
|
DataPack = []
|
@@ -187,7 +189,7 @@ class SnapshotCore:
|
|
187
189
|
# print(f'获取快照数据包返回值:{DataPack}')
|
188
190
|
return DataPack
|
189
191
|
|
190
|
-
@retry(max_attempts=3, delay=0.5)
|
192
|
+
@retry(max_attempts=3, delay=0.5, assign_exception=SnapshotTimeoutError)
|
191
193
|
async def get_data_pack_h_address(
|
192
194
|
self, register_num: int
|
193
195
|
) -> List: # 取得数据包大小
|
@@ -197,7 +199,7 @@ class SnapshotCore:
|
|
197
199
|
)
|
198
200
|
return data
|
199
201
|
|
200
|
-
@retry(max_attempts=3, delay=0.5)
|
202
|
+
@retry(max_attempts=3, delay=0.5, assign_exception=SnapshotTimeoutError)
|
201
203
|
async def _get_data_pack_l_address(
|
202
204
|
self, register_num: int
|
203
205
|
) -> List: # 取得数据包大小
|
@@ -207,7 +209,7 @@ class SnapshotCore:
|
|
207
209
|
)
|
208
210
|
return data
|
209
211
|
|
210
|
-
@retry(max_attempts=5, delay=0.2)
|
212
|
+
@retry(max_attempts=5, delay=0.2, assign_exception=SnapshotTimeoutError)
|
211
213
|
async def _clear_data_pack_read_state(self): # 清除数据包读取状态
|
212
214
|
# print(f'清除数据包读取状态')
|
213
215
|
await self.modbus.write_registers(
|
@@ -1,3 +1,3 @@
|
|
1
|
-
from .snap_shot import SnapshotError, SnapshotTimeoutError
|
2
|
-
|
3
|
-
__all__ = ["SnapshotError", "SnapshotTimeoutError"]
|
1
|
+
from .snap_shot import SnapshotError, SnapshotTimeoutError
|
2
|
+
|
3
|
+
__all__ = ["SnapshotError", "SnapshotTimeoutError"]
|
@@ -1,9 +1,9 @@
|
|
1
|
-
from solax_py_library.exception import SolaxBaseError
|
2
|
-
|
3
|
-
|
4
|
-
class SnapshotError(SolaxBaseError):
|
5
|
-
...
|
6
|
-
|
7
|
-
|
8
|
-
class SnapshotTimeoutError(SnapshotError):
|
9
|
-
...
|
1
|
+
from solax_py_library.exception import SolaxBaseError
|
2
|
+
|
3
|
+
|
4
|
+
class SnapshotError(SolaxBaseError):
|
5
|
+
...
|
6
|
+
|
7
|
+
|
8
|
+
class SnapshotTimeoutError(SnapshotError):
|
9
|
+
...
|
@@ -1,15 +1,15 @@
|
|
1
|
-
from .address import (
|
2
|
-
SnapshotMCUSource,
|
3
|
-
SnapshotRegisterAddress,
|
4
|
-
SnapshotStartResult,
|
5
|
-
SnapshotExportDevice,
|
6
|
-
CommandType,
|
7
|
-
)
|
8
|
-
|
9
|
-
__all__ = [
|
10
|
-
"SnapshotMCUSource",
|
11
|
-
"SnapshotRegisterAddress",
|
12
|
-
"SnapshotStartResult",
|
13
|
-
"SnapshotExportDevice",
|
14
|
-
"CommandType",
|
15
|
-
]
|
1
|
+
from .address import (
|
2
|
+
SnapshotMCUSource,
|
3
|
+
SnapshotRegisterAddress,
|
4
|
+
SnapshotStartResult,
|
5
|
+
SnapshotExportDevice,
|
6
|
+
CommandType,
|
7
|
+
)
|
8
|
+
|
9
|
+
__all__ = [
|
10
|
+
"SnapshotMCUSource",
|
11
|
+
"SnapshotRegisterAddress",
|
12
|
+
"SnapshotStartResult",
|
13
|
+
"SnapshotExportDevice",
|
14
|
+
"CommandType",
|
15
|
+
]
|