solax-py-library 1.0.0.24__py3-none-any.whl → 1.0.0.26__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/cabinet.py +2 -0
- 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/alarm.py +16 -0
- 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 +179 -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/action/base.py +10 -0
- solax_py_library/smart_scene/core/action/ems_action.py +6 -0
- solax_py_library/smart_scene/core/action/system_action.py +6 -0
- solax_py_library/smart_scene/core/condition/__init__.py +17 -0
- solax_py_library/smart_scene/core/condition/base.py +17 -0
- solax_py_library/smart_scene/core/condition/cabinet_condition.py +44 -0
- solax_py_library/smart_scene/core/condition/date_condition.py +23 -0
- solax_py_library/smart_scene/core/condition/price_condition.py +110 -0
- solax_py_library/smart_scene/core/condition/system_condition.py +35 -0
- solax_py_library/smart_scene/core/condition/weather_condition.py +61 -0
- solax_py_library/smart_scene/core/service/__init__.py +3 -0
- solax_py_library/smart_scene/core/service/runner.py +156 -0
- solax_py_library/smart_scene/exceptions/__init__.py +7 -0
- solax_py_library/smart_scene/exceptions/price.py +5 -0
- solax_py_library/smart_scene/exceptions/smart_scene.py +82 -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 +164 -0
- solax_py_library/smart_scene/types/condition.py +299 -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_smart_scene/__init__.py +0 -0
- solax_py_library/test/test_smart_scene/test_condition.py +11 -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 +42 -30
- solax_py_library/utils/time_util.py +38 -0
- {solax_py_library-1.0.0.24.dist-info → solax_py_library-1.0.0.26.dist-info}/METADATA +2 -1
- solax_py_library-1.0.0.26.dist-info/RECORD +80 -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.26.dist-info}/WHEEL +0 -0
File without changes
|
File without changes
|
@@ -0,0 +1,11 @@
|
|
1
|
+
from unittest import TestCase
|
2
|
+
|
3
|
+
from solax_py_library.smart_scene.core.condition import DateCondition, BaseCondition
|
4
|
+
|
5
|
+
|
6
|
+
class TestCondition(TestCase):
|
7
|
+
def test_condition(self):
|
8
|
+
date_condition = DateCondition(
|
9
|
+
update_value_function=lambda: 1,
|
10
|
+
)
|
11
|
+
assert isinstance(date_condition, BaseCondition)
|
File without changes
|
@@ -0,0 +1,14 @@
|
|
1
|
+
from unittest import TestCase
|
2
|
+
|
3
|
+
from solax_py_library.utils.cloud_client import CloudClient
|
4
|
+
|
5
|
+
|
6
|
+
class TestCloudClient(TestCase):
|
7
|
+
def test_get_weather(self):
|
8
|
+
client = CloudClient()
|
9
|
+
ret = client.get_weather_data_from_cloud(
|
10
|
+
"https://aliyun-sit.solaxtech.net:5050",
|
11
|
+
"XMG11A011L",
|
12
|
+
"b080a22827484db6bd509d496f9df90b",
|
13
|
+
)
|
14
|
+
print(ret)
|
@@ -1,3 +1,3 @@
|
|
1
|
-
from . import api, types, core, exceptions
|
2
|
-
|
3
|
-
__all__ = ["api", "core", "exceptions", "types"]
|
1
|
+
from . import api, types, core, exceptions
|
2
|
+
|
3
|
+
__all__ = ["api", "core", "exceptions", "types"]
|
@@ -1,3 +1,3 @@
|
|
1
|
-
from .service import upload, upload_service
|
2
|
-
|
3
|
-
__all__ = ["upload", "upload_service"]
|
1
|
+
from .service import upload, upload_service
|
2
|
+
|
3
|
+
__all__ = ["upload", "upload_service"]
|
@@ -1,24 +1,24 @@
|
|
1
|
-
from typing import Dict, Any
|
2
|
-
|
3
|
-
from solax_py_library.upload.core.upload_service import upload_service_map
|
4
|
-
from solax_py_library.exception import SolaxBaseError
|
5
|
-
from solax_py_library.upload.types.client import UploadType, UploadData
|
6
|
-
|
7
|
-
|
8
|
-
def upload_service(upload_type: UploadType, configuration: Dict[str, Any]):
|
9
|
-
"""
|
10
|
-
upload_type: 上传类型。
|
11
|
-
configuration: 配置信息
|
12
|
-
"""
|
13
|
-
upload_class = upload_service_map.get(upload_type)
|
14
|
-
if not upload_class:
|
15
|
-
raise SolaxBaseError
|
16
|
-
return upload_class(**configuration)
|
17
|
-
|
18
|
-
|
19
|
-
async def upload(
|
20
|
-
upload_type: UploadType, configuration: Dict[str, Any], upload_data: UploadData
|
21
|
-
):
|
22
|
-
service = upload_service(upload_type, configuration)
|
23
|
-
with service as s:
|
24
|
-
await s.upload(upload_data)
|
1
|
+
from typing import Dict, Any
|
2
|
+
|
3
|
+
from solax_py_library.upload.core.upload_service import upload_service_map
|
4
|
+
from solax_py_library.exception import SolaxBaseError
|
5
|
+
from solax_py_library.upload.types.client import UploadType, UploadData
|
6
|
+
|
7
|
+
|
8
|
+
def upload_service(upload_type: UploadType, configuration: Dict[str, Any]):
|
9
|
+
"""
|
10
|
+
upload_type: 上传类型。
|
11
|
+
configuration: 配置信息
|
12
|
+
"""
|
13
|
+
upload_class = upload_service_map.get(upload_type)
|
14
|
+
if not upload_class:
|
15
|
+
raise SolaxBaseError
|
16
|
+
return upload_class(**configuration)
|
17
|
+
|
18
|
+
|
19
|
+
async def upload(
|
20
|
+
upload_type: UploadType, configuration: Dict[str, Any], upload_data: UploadData
|
21
|
+
):
|
22
|
+
service = upload_service(upload_type, configuration)
|
23
|
+
with service as s:
|
24
|
+
await s.upload(upload_data)
|
@@ -1,3 +1,3 @@
|
|
1
|
-
from . import upload_service, data_adapter
|
2
|
-
|
3
|
-
__all__ = ["upload_service", "data_adapter"]
|
1
|
+
from . import upload_service, data_adapter
|
2
|
+
|
3
|
+
__all__ = ["upload_service", "data_adapter"]
|
@@ -1,5 +1,5 @@
|
|
1
|
-
from .base import BaseDataAdapter
|
2
|
-
from .csv import CSVDataAdapter
|
3
|
-
|
4
|
-
|
5
|
-
__all__ = ["BaseDataAdapter", "CSVDataAdapter"]
|
1
|
+
from .base import BaseDataAdapter
|
2
|
+
from .csv import CSVDataAdapter
|
3
|
+
|
4
|
+
|
5
|
+
__all__ = ["BaseDataAdapter", "CSVDataAdapter"]
|
@@ -1,9 +1,9 @@
|
|
1
|
-
from abc import ABCMeta, abstractmethod
|
2
|
-
|
3
|
-
|
4
|
-
class BaseDataAdapter(metaclass=ABCMeta):
|
5
|
-
data_type = None
|
6
|
-
|
7
|
-
@abstractmethod
|
8
|
-
def parse_data(self, data):
|
9
|
-
...
|
1
|
+
from abc import ABCMeta, abstractmethod
|
2
|
+
|
3
|
+
|
4
|
+
class BaseDataAdapter(metaclass=ABCMeta):
|
5
|
+
data_type = None
|
6
|
+
|
7
|
+
@abstractmethod
|
8
|
+
def parse_data(self, data):
|
9
|
+
...
|
@@ -1,26 +1,26 @@
|
|
1
|
-
import csv
|
2
|
-
import tempfile
|
3
|
-
from typing import Any, Union, List, Dict
|
4
|
-
|
5
|
-
from solax_py_library.upload.core.data_adapter.base import BaseDataAdapter
|
6
|
-
|
7
|
-
|
8
|
-
class CSVDataAdapter(BaseDataAdapter):
|
9
|
-
@classmethod
|
10
|
-
def parse_data(cls, data: Union[List[List[Any]], List[Dict[str, Any]]]):
|
11
|
-
with tempfile.NamedTemporaryFile(
|
12
|
-
delete=False, mode="w", newline="", encoding="utf-8-sig"
|
13
|
-
) as temp_file:
|
14
|
-
if isinstance(data[0], list):
|
15
|
-
writer = csv.writer(temp_file)
|
16
|
-
writer.writerows(data)
|
17
|
-
else:
|
18
|
-
headers = list(data[0].keys())
|
19
|
-
writer = csv.DictWriter(temp_file, fieldnames=headers)
|
20
|
-
writer.writeheader()
|
21
|
-
writer.writerows(data)
|
22
|
-
|
23
|
-
temp_file_path = temp_file.name
|
24
|
-
temp_file.seek(0)
|
25
|
-
|
26
|
-
return temp_file_path
|
1
|
+
import csv
|
2
|
+
import tempfile
|
3
|
+
from typing import Any, Union, List, Dict
|
4
|
+
|
5
|
+
from solax_py_library.upload.core.data_adapter.base import BaseDataAdapter
|
6
|
+
|
7
|
+
|
8
|
+
class CSVDataAdapter(BaseDataAdapter):
|
9
|
+
@classmethod
|
10
|
+
def parse_data(cls, data: Union[List[List[Any]], List[Dict[str, Any]]]):
|
11
|
+
with tempfile.NamedTemporaryFile(
|
12
|
+
delete=False, mode="w", newline="", encoding="utf-8-sig"
|
13
|
+
) as temp_file:
|
14
|
+
if isinstance(data[0], list):
|
15
|
+
writer = csv.writer(temp_file)
|
16
|
+
writer.writerows(data)
|
17
|
+
else:
|
18
|
+
headers = list(data[0].keys())
|
19
|
+
writer = csv.DictWriter(temp_file, fieldnames=headers)
|
20
|
+
writer.writeheader()
|
21
|
+
writer.writerows(data)
|
22
|
+
|
23
|
+
temp_file_path = temp_file.name
|
24
|
+
temp_file.seek(0)
|
25
|
+
|
26
|
+
return temp_file_path
|
@@ -1,15 +1,15 @@
|
|
1
|
-
from .base import BaseUploadService
|
2
|
-
from .ftp import FTPUploadService
|
3
|
-
|
4
|
-
|
5
|
-
upload_service_map = {}
|
6
|
-
|
7
|
-
|
8
|
-
def _register(upload_obj):
|
9
|
-
upload_service_map[upload_obj.upload_type] = upload_obj
|
10
|
-
|
11
|
-
|
12
|
-
_register(FTPUploadService)
|
13
|
-
|
14
|
-
|
15
|
-
__all__ = ["BaseUploadService", "FTPUploadService"]
|
1
|
+
from .base import BaseUploadService
|
2
|
+
from .ftp import FTPUploadService
|
3
|
+
|
4
|
+
|
5
|
+
upload_service_map = {}
|
6
|
+
|
7
|
+
|
8
|
+
def _register(upload_obj):
|
9
|
+
upload_service_map[upload_obj.upload_type] = upload_obj
|
10
|
+
|
11
|
+
|
12
|
+
_register(FTPUploadService)
|
13
|
+
|
14
|
+
|
15
|
+
__all__ = ["BaseUploadService", "FTPUploadService"]
|
@@ -1,43 +1,43 @@
|
|
1
|
-
from abc import ABCMeta, abstractmethod
|
2
|
-
|
3
|
-
from solax_py_library.upload.types.client import UploadData
|
4
|
-
|
5
|
-
|
6
|
-
class BaseUploadService(metaclass=ABCMeta):
|
7
|
-
upload_type = None
|
8
|
-
|
9
|
-
def __init__(self, **kwargs) -> None:
|
10
|
-
self._client = None
|
11
|
-
self._is_connect = False
|
12
|
-
self.timeout = 5
|
13
|
-
|
14
|
-
@abstractmethod
|
15
|
-
def connect(self):
|
16
|
-
...
|
17
|
-
|
18
|
-
async def upload(self, data: UploadData):
|
19
|
-
upload_data = self._parse(data.build_data())
|
20
|
-
return self._upload(upload_data)
|
21
|
-
|
22
|
-
@abstractmethod
|
23
|
-
def close(self):
|
24
|
-
...
|
25
|
-
|
26
|
-
@property
|
27
|
-
def is_connect(self):
|
28
|
-
return self._is_connect
|
29
|
-
|
30
|
-
def __enter__(self):
|
31
|
-
self.connect()
|
32
|
-
return self
|
33
|
-
|
34
|
-
def __exit__(self, exc_type, exc_value, traceback):
|
35
|
-
self.close()
|
36
|
-
|
37
|
-
@abstractmethod
|
38
|
-
def _upload(self, data):
|
39
|
-
...
|
40
|
-
|
41
|
-
@abstractmethod
|
42
|
-
def _parse(self, upload_data: UploadData):
|
43
|
-
...
|
1
|
+
from abc import ABCMeta, abstractmethod
|
2
|
+
|
3
|
+
from solax_py_library.upload.types.client import UploadData
|
4
|
+
|
5
|
+
|
6
|
+
class BaseUploadService(metaclass=ABCMeta):
|
7
|
+
upload_type = None
|
8
|
+
|
9
|
+
def __init__(self, **kwargs) -> None:
|
10
|
+
self._client = None
|
11
|
+
self._is_connect = False
|
12
|
+
self.timeout = 5
|
13
|
+
|
14
|
+
@abstractmethod
|
15
|
+
def connect(self):
|
16
|
+
...
|
17
|
+
|
18
|
+
async def upload(self, data: UploadData):
|
19
|
+
upload_data = self._parse(data.build_data())
|
20
|
+
return self._upload(upload_data)
|
21
|
+
|
22
|
+
@abstractmethod
|
23
|
+
def close(self):
|
24
|
+
...
|
25
|
+
|
26
|
+
@property
|
27
|
+
def is_connect(self):
|
28
|
+
return self._is_connect
|
29
|
+
|
30
|
+
def __enter__(self):
|
31
|
+
self.connect()
|
32
|
+
return self
|
33
|
+
|
34
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
35
|
+
self.close()
|
36
|
+
|
37
|
+
@abstractmethod
|
38
|
+
def _upload(self, data):
|
39
|
+
...
|
40
|
+
|
41
|
+
@abstractmethod
|
42
|
+
def _parse(self, upload_data: UploadData):
|
43
|
+
...
|
@@ -1,8 +1,8 @@
|
|
1
|
-
from .upload_error import ConfigurationError, ConnectError, LoginError, SendDataError
|
2
|
-
|
3
|
-
__all__ = [
|
4
|
-
"ConnectError",
|
5
|
-
"LoginError",
|
6
|
-
"SendDataError",
|
7
|
-
"ConfigurationError",
|
8
|
-
]
|
1
|
+
from .upload_error import ConfigurationError, ConnectError, LoginError, SendDataError
|
2
|
+
|
3
|
+
__all__ = [
|
4
|
+
"ConnectError",
|
5
|
+
"LoginError",
|
6
|
+
"SendDataError",
|
7
|
+
"ConfigurationError",
|
8
|
+
]
|
@@ -1,21 +1,21 @@
|
|
1
|
-
from solax_py_library.exception import SolaxBaseError
|
2
|
-
|
3
|
-
|
4
|
-
class ConnectError(SolaxBaseError):
|
5
|
-
code = 0x1001
|
6
|
-
message = "connect error"
|
7
|
-
|
8
|
-
|
9
|
-
class LoginError(SolaxBaseError):
|
10
|
-
code = 0x1002
|
11
|
-
message = "authentication error"
|
12
|
-
|
13
|
-
|
14
|
-
class SendDataError(SolaxBaseError):
|
15
|
-
code = 0x1003
|
16
|
-
message = "send data error"
|
17
|
-
|
18
|
-
|
19
|
-
class ConfigurationError(SolaxBaseError):
|
20
|
-
code = 0x1004
|
21
|
-
message = "server configuration error"
|
1
|
+
from solax_py_library.exception import SolaxBaseError
|
2
|
+
|
3
|
+
|
4
|
+
class ConnectError(SolaxBaseError):
|
5
|
+
code = 0x1001
|
6
|
+
message = "connect error"
|
7
|
+
|
8
|
+
|
9
|
+
class LoginError(SolaxBaseError):
|
10
|
+
code = 0x1002
|
11
|
+
message = "authentication error"
|
12
|
+
|
13
|
+
|
14
|
+
class SendDataError(SolaxBaseError):
|
15
|
+
code = 0x1003
|
16
|
+
message = "send data error"
|
17
|
+
|
18
|
+
|
19
|
+
class ConfigurationError(SolaxBaseError):
|
20
|
+
code = 0x1004
|
21
|
+
message = "server configuration error"
|
@@ -1,113 +1,113 @@
|
|
1
|
-
import asyncio
|
2
|
-
import unittest
|
3
|
-
|
4
|
-
from solax_py_library.upload.api.service import upload
|
5
|
-
from solax_py_library.upload.core.upload_service import FTPUploadService
|
6
|
-
from solax_py_library.upload.exceptions import ConnectError, LoginError
|
7
|
-
from solax_py_library.upload.types.client import UploadType, UploadData
|
8
|
-
from solax_py_library.upload.types.ftp import FTPFileType
|
9
|
-
|
10
|
-
|
11
|
-
class FTPTest(unittest.TestCase):
|
12
|
-
def test_connect(self):
|
13
|
-
ftp_config = {
|
14
|
-
"host": "10.1.31.181", # 测试host
|
15
|
-
"port": 21,
|
16
|
-
"user": "solax",
|
17
|
-
"password": "123456",
|
18
|
-
"remote_path": "/xixi",
|
19
|
-
}
|
20
|
-
ftp = FTPUploadService(**ftp_config)
|
21
|
-
ftp.connect()
|
22
|
-
|
23
|
-
def test_connect_error_1(self):
|
24
|
-
ftp_config = {
|
25
|
-
"host": "10.1.31.182", # 测试host
|
26
|
-
"port": 21,
|
27
|
-
"user": "solax",
|
28
|
-
"password": "123456",
|
29
|
-
"remote_path": "/xixi",
|
30
|
-
}
|
31
|
-
ftp = FTPUploadService(**ftp_config)
|
32
|
-
try:
|
33
|
-
ftp.connect()
|
34
|
-
except ConnectError:
|
35
|
-
...
|
36
|
-
|
37
|
-
def test_connect_error_2(self):
|
38
|
-
ftp_config = {
|
39
|
-
"host": "10.1.31.181", # 测试host
|
40
|
-
"port": 21,
|
41
|
-
"user": "solax123",
|
42
|
-
"password": "123456",
|
43
|
-
"remote_path": "/xixi",
|
44
|
-
}
|
45
|
-
ftp = FTPUploadService(**ftp_config)
|
46
|
-
try:
|
47
|
-
ftp.connect()
|
48
|
-
except LoginError:
|
49
|
-
...
|
50
|
-
|
51
|
-
def test_ftp_upload_to_windows(self):
|
52
|
-
ftp_config = {
|
53
|
-
"host": "10.1.31.181", # 测试host
|
54
|
-
"port": 21,
|
55
|
-
"user": "solax",
|
56
|
-
"password": "123456",
|
57
|
-
"remote_path": "嘻嘻",
|
58
|
-
}
|
59
|
-
asyncio.run(
|
60
|
-
upload(
|
61
|
-
upload_type=UploadType.FTP,
|
62
|
-
configuration=ftp_config,
|
63
|
-
upload_data=UploadData(
|
64
|
-
upload_type=UploadType.FTP,
|
65
|
-
data=dict(
|
66
|
-
file_type=FTPFileType.CSV,
|
67
|
-
file_name="中文",
|
68
|
-
data=[
|
69
|
-
{
|
70
|
-
"EMS1000序列号": "XMG11A011L",
|
71
|
-
"EMS1000本地时间": "2025-02-11 15:39:10",
|
72
|
-
"EMS1000版本号": "V007.11.1",
|
73
|
-
"电站所在国家和地区": None,
|
74
|
-
"电站所在当前时区": None,
|
75
|
-
"电站系统类型": None,
|
76
|
-
}
|
77
|
-
],
|
78
|
-
),
|
79
|
-
),
|
80
|
-
)
|
81
|
-
)
|
82
|
-
|
83
|
-
def test_ftp_upload_to_linux(self):
|
84
|
-
ftp_config = {
|
85
|
-
"host": "920729yofx76.vicp.fun", # 测试host
|
86
|
-
"port": 59477,
|
87
|
-
"user": "test",
|
88
|
-
"password": "test123456",
|
89
|
-
"remote_path": "test",
|
90
|
-
}
|
91
|
-
asyncio.run(
|
92
|
-
upload(
|
93
|
-
upload_type=UploadType.FTP,
|
94
|
-
configuration=ftp_config,
|
95
|
-
upload_data=UploadData(
|
96
|
-
upload_type=UploadType.FTP,
|
97
|
-
data=dict(
|
98
|
-
file_type=FTPFileType.CSV,
|
99
|
-
file_name="中文",
|
100
|
-
data=[
|
101
|
-
{
|
102
|
-
"EMS1000序列号": "XMG11A011L",
|
103
|
-
"EMS1000本地时间": "2025-02-11 15:39:10",
|
104
|
-
"EMS1000版本号": "V007.11.1",
|
105
|
-
"电站所在国家和地区": None,
|
106
|
-
"电站所在当前时区": None,
|
107
|
-
"电站系统类型": None,
|
108
|
-
}
|
109
|
-
],
|
110
|
-
),
|
111
|
-
),
|
112
|
-
)
|
113
|
-
)
|
1
|
+
import asyncio
|
2
|
+
import unittest
|
3
|
+
|
4
|
+
from solax_py_library.upload.api.service import upload
|
5
|
+
from solax_py_library.upload.core.upload_service import FTPUploadService
|
6
|
+
from solax_py_library.upload.exceptions import ConnectError, LoginError
|
7
|
+
from solax_py_library.upload.types.client import UploadType, UploadData
|
8
|
+
from solax_py_library.upload.types.ftp import FTPFileType
|
9
|
+
|
10
|
+
|
11
|
+
class FTPTest(unittest.TestCase):
|
12
|
+
def test_connect(self):
|
13
|
+
ftp_config = {
|
14
|
+
"host": "10.1.31.181", # 测试host
|
15
|
+
"port": 21,
|
16
|
+
"user": "solax",
|
17
|
+
"password": "123456",
|
18
|
+
"remote_path": "/xixi",
|
19
|
+
}
|
20
|
+
ftp = FTPUploadService(**ftp_config)
|
21
|
+
ftp.connect()
|
22
|
+
|
23
|
+
def test_connect_error_1(self):
|
24
|
+
ftp_config = {
|
25
|
+
"host": "10.1.31.182", # 测试host
|
26
|
+
"port": 21,
|
27
|
+
"user": "solax",
|
28
|
+
"password": "123456",
|
29
|
+
"remote_path": "/xixi",
|
30
|
+
}
|
31
|
+
ftp = FTPUploadService(**ftp_config)
|
32
|
+
try:
|
33
|
+
ftp.connect()
|
34
|
+
except ConnectError:
|
35
|
+
...
|
36
|
+
|
37
|
+
def test_connect_error_2(self):
|
38
|
+
ftp_config = {
|
39
|
+
"host": "10.1.31.181", # 测试host
|
40
|
+
"port": 21,
|
41
|
+
"user": "solax123",
|
42
|
+
"password": "123456",
|
43
|
+
"remote_path": "/xixi",
|
44
|
+
}
|
45
|
+
ftp = FTPUploadService(**ftp_config)
|
46
|
+
try:
|
47
|
+
ftp.connect()
|
48
|
+
except LoginError:
|
49
|
+
...
|
50
|
+
|
51
|
+
def test_ftp_upload_to_windows(self):
|
52
|
+
ftp_config = {
|
53
|
+
"host": "10.1.31.181", # 测试host
|
54
|
+
"port": 21,
|
55
|
+
"user": "solax",
|
56
|
+
"password": "123456",
|
57
|
+
"remote_path": "嘻嘻",
|
58
|
+
}
|
59
|
+
asyncio.run(
|
60
|
+
upload(
|
61
|
+
upload_type=UploadType.FTP,
|
62
|
+
configuration=ftp_config,
|
63
|
+
upload_data=UploadData(
|
64
|
+
upload_type=UploadType.FTP,
|
65
|
+
data=dict(
|
66
|
+
file_type=FTPFileType.CSV,
|
67
|
+
file_name="中文",
|
68
|
+
data=[
|
69
|
+
{
|
70
|
+
"EMS1000序列号": "XMG11A011L",
|
71
|
+
"EMS1000本地时间": "2025-02-11 15:39:10",
|
72
|
+
"EMS1000版本号": "V007.11.1",
|
73
|
+
"电站所在国家和地区": None,
|
74
|
+
"电站所在当前时区": None,
|
75
|
+
"电站系统类型": None,
|
76
|
+
}
|
77
|
+
],
|
78
|
+
),
|
79
|
+
),
|
80
|
+
)
|
81
|
+
)
|
82
|
+
|
83
|
+
def test_ftp_upload_to_linux(self):
|
84
|
+
ftp_config = {
|
85
|
+
"host": "920729yofx76.vicp.fun", # 测试host
|
86
|
+
"port": 59477,
|
87
|
+
"user": "test",
|
88
|
+
"password": "test123456",
|
89
|
+
"remote_path": "test",
|
90
|
+
}
|
91
|
+
asyncio.run(
|
92
|
+
upload(
|
93
|
+
upload_type=UploadType.FTP,
|
94
|
+
configuration=ftp_config,
|
95
|
+
upload_data=UploadData(
|
96
|
+
upload_type=UploadType.FTP,
|
97
|
+
data=dict(
|
98
|
+
file_type=FTPFileType.CSV,
|
99
|
+
file_name="中文",
|
100
|
+
data=[
|
101
|
+
{
|
102
|
+
"EMS1000序列号": "XMG11A011L",
|
103
|
+
"EMS1000本地时间": "2025-02-11 15:39:10",
|
104
|
+
"EMS1000版本号": "V007.11.1",
|
105
|
+
"电站所在国家和地区": None,
|
106
|
+
"电站所在当前时区": None,
|
107
|
+
"电站系统类型": None,
|
108
|
+
}
|
109
|
+
],
|
110
|
+
),
|
111
|
+
),
|
112
|
+
)
|
113
|
+
)
|
@@ -1,11 +1,11 @@
|
|
1
|
-
from .client import UploadType, UploadData
|
2
|
-
from .ftp import FTPData, FTPParsedData, FTPFileType, FTPServiceConfig
|
3
|
-
|
4
|
-
__all__ = [
|
5
|
-
"FTPData",
|
6
|
-
"FTPParsedData",
|
7
|
-
"FTPServiceConfig",
|
8
|
-
"UploadType",
|
9
|
-
"UploadData",
|
10
|
-
"FTPFileType",
|
11
|
-
]
|
1
|
+
from .client import UploadType, UploadData
|
2
|
+
from .ftp import FTPData, FTPParsedData, FTPFileType, FTPServiceConfig
|
3
|
+
|
4
|
+
__all__ = [
|
5
|
+
"FTPData",
|
6
|
+
"FTPParsedData",
|
7
|
+
"FTPServiceConfig",
|
8
|
+
"UploadType",
|
9
|
+
"UploadData",
|
10
|
+
"FTPFileType",
|
11
|
+
]
|
@@ -1,19 +1,19 @@
|
|
1
|
-
from enum import IntEnum
|
2
|
-
from pydantic import BaseModel
|
3
|
-
from typing import Optional, Union
|
4
|
-
|
5
|
-
from solax_py_library.upload.types.ftp import FTPData
|
6
|
-
|
7
|
-
|
8
|
-
class UploadType(IntEnum):
|
9
|
-
FTP = 1
|
10
|
-
|
11
|
-
|
12
|
-
class UploadData(BaseModel):
|
13
|
-
data: Optional[Union[dict, FTPData]]
|
14
|
-
upload_type: UploadType
|
15
|
-
|
16
|
-
def build_data(self):
|
17
|
-
dict_obj_data = self.data if isinstance(self.data, dict) else self.data.dict()
|
18
|
-
if self.upload_type == UploadType.FTP:
|
19
|
-
return FTPData(**dict_obj_data)
|
1
|
+
from enum import IntEnum
|
2
|
+
from pydantic import BaseModel
|
3
|
+
from typing import Optional, Union
|
4
|
+
|
5
|
+
from solax_py_library.upload.types.ftp import FTPData
|
6
|
+
|
7
|
+
|
8
|
+
class UploadType(IntEnum):
|
9
|
+
FTP = 1
|
10
|
+
|
11
|
+
|
12
|
+
class UploadData(BaseModel):
|
13
|
+
data: Optional[Union[dict, FTPData]]
|
14
|
+
upload_type: UploadType
|
15
|
+
|
16
|
+
def build_data(self):
|
17
|
+
dict_obj_data = self.data if isinstance(self.data, dict) else self.data.dict()
|
18
|
+
if self.upload_type == UploadType.FTP:
|
19
|
+
return FTPData(**dict_obj_data)
|