Compare commits
No commits in common. "main" and "master" have entirely different histories.
|
|
@ -1,162 +0,0 @@
|
|||
# ---> Python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.10" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Black">
|
||||
<option name="sdkName" value="Python 3.10" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/Scripts.iml" filepath="$PROJECT_DIR$/.idea/Scripts.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"MicroPython.executeButton": [
|
||||
{
|
||||
"text": "▶",
|
||||
"tooltip": "运行",
|
||||
"alignment": "left",
|
||||
"command": "extension.executeFile",
|
||||
"priority": 3.5
|
||||
}
|
||||
],
|
||||
"MicroPython.syncButton": [
|
||||
{
|
||||
"text": "$(sync)",
|
||||
"tooltip": "同步",
|
||||
"alignment": "left",
|
||||
"command": "extension.execute",
|
||||
"priority": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
2024-04-11 20:23:56.466 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ControlType: ListItemControl}
|
||||
2024-04-11 20:24:06.474 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ControlType: ListItemControl}
|
||||
2024-04-11 20:24:16.517 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ControlType: ListItemControl}
|
||||
2024-04-11 20:24:26.567 pydevd_resolver.py[189] _get_py_dictionary -> 2024-04-11 21:07:33.369 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {Control: 6160838, ControlType: DataGridControl}
|
||||
2024-04-11 21:07:45.575 pydevd_resolver.py[189] _get_py_dictionary -> 2024-04-11 21:17:30.731 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ClassName: 'TMyListView', ControlType: DataGridControl}
|
||||
2024-04-11 21:17:41.020 pydevd_resolver.py[189] _get_py_dictionary -> 2024-04-11 21:18:15.553 pydevd_resolver.py[189] _get_py_dictionary -> 2024-04-11 21:18:47.237 pydevd_resolver.py[189] _get_py_dictionary -> 2024-05-27 19:00:04.823 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {Name: 'AACE 登录', ControlType: WindowControl}
|
||||
2024-05-27 19:00:14.991 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {Name: 'AACE 登录', ControlType: WindowControl}
|
||||
2024-05-27 19:00:25.181 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {Name: 'AACE 登录', ControlType: WindowControl}
|
||||
2024-05-27 19:00:35.334 pydevd_resolver.py[189] _get_py_dictionary -> 2024-05-28 16:48:40.572 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ControlType: ListControl}
|
||||
2024-05-28 16:48:50.705 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ControlType: ListControl}
|
||||
2024-05-28 16:49:00.704 pydevd_resolver.py[189] _get_py_dictionary -> 2024-05-29 15:21:38.378 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ClassName: 'TMyListView', ControlType: DataGridControl}
|
||||
2024-05-29 15:21:48.827 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ClassName: 'TMyListView', ControlType: DataGridControl}
|
||||
2024-05-29 15:21:59.232 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ClassName: 'TMyListView', ControlType: DataGridControl}
|
||||
2024-05-29 15:22:09.638 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ClassName: 'TMyListView', ControlType: DataGridControl}
|
||||
2024-05-29 15:22:19.706 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ClassName: 'TMyListView', ControlType: DataGridControl}
|
||||
2024-05-29 15:22:30.139 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ClassName: 'TMyListView', ControlType: DataGridControl}
|
||||
2024-05-29 15:22:40.564 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ClassName: 'TMyListView', ControlType: DataGridControl}
|
||||
2024-05-29 15:22:51.016 pydevd_resolver.py[189] _get_py_dictionary -> 2024-05-29 15:25:05.120 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ControlType: DataGridControl}
|
||||
2024-05-29 15:25:15.708 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ControlType: DataGridControl}
|
||||
2024-05-29 15:25:26.312 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ControlType: DataGridControl}
|
||||
2024-05-29 15:25:36.881 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ControlType: DataGridControl}
|
||||
2024-05-29 15:25:47.480 pydevd_resolver.py[189] _get_py_dictionary -> 2024-05-29 17:20:34.260 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ClassName: 'TMyListView', ControlType: DataGridControl}
|
||||
2024-05-29 17:20:44.778 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ClassName: 'TMyListView', ControlType: DataGridControl}
|
||||
2024-05-29 17:20:55.294 pydevd_resolver.py[189] _get_py_dictionary -> 2024-05-29 17:22:53.176 pydevd_resolver.py[189] _get_py_dictionary -> 2024-05-29 17:23:27.293 pydevd_resolver.py[189] _get_py_dictionary -> Find Control Timeout(10s): {ControlType: DataGridControl}
|
||||
2024-05-29 17:23:37.679 pydevd_resolver.py[189] _get_py_dictionary -> 2024-05-29 17:24:09.109 pydevd_resolver.py[189] _get_py_dictionary -> 2025-01-21 13:49:35.431 1.py[354] click_create_table -> 2025-01-22 11:04:23.034 aacecontrol.py[493] is_finished -> Find Control Timeout(10s): {ClassName: 'TMyListView', ControlType: ListControl}
|
||||
2025-01-22 11:04:37.901 pydevd_resolver.py[189] _get_py_dictionary ->
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
分析名称 : 氨氮.ANL
|
||||
运行名称 : 230818E.run
|
||||
运行日期 : 2023/8/18
|
||||
报告日期 : 2024/4/11
|
||||
评论 :
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
1. 未更正的值, 通道: 1
|
||||
|
||||
Pk# Type Cl. CLP Group Digit Conc mAU Start Pos R A Weight Dilution
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
0 B 0 1 0 8414 0.0000 0.00 807 813 0 0 1.000 1.000
|
||||
1 P & 0 0 0 25031 0.0000 362.23 840 899 0 0 1.000 1.000
|
||||
2 D A 0 0 0 25282 0.0000 367.70 960 1017 0 0 1.000 1.000
|
||||
3 N A 0 0 0 8531 0.0000 2.55 1080 1157 0 0 1.000 1.000
|
||||
4 C A 0 0 0 11168 2.0000 60.03 1200 1258 0 0 1.000 1.000
|
||||
5 C A 0 0 0 14476 4.0000 132.14 1320 1380 0 0 1.000 1.000
|
||||
6 C A 0 0 0 18484 6.0000 219.51 1440 1496 0 0 1.000 1.000
|
||||
7 C A 0 0 0 21860 8.0000 293.10 1560 1612 0 0 1.000 1.000
|
||||
8 C A 0 0 0 25795 10.0000 378.88 1680 1739 0 0 1.000 1.000
|
||||
9 N A 0 0 0 8553 0.6484 3.03 1800 1877 0 0 1.000 1.000
|
||||
10 S A 0 0 0 14226 3.7452 126.69 1920 1970 0 0 1.000 1.000
|
||||
11 S A 0 0 0 11593 2.3079 69.30 2040 2086 0 0 1.000 1.000
|
||||
12 S A 0 0 0 12282 2.6840 84.32 2160 2212 0 0 1.000 1.000
|
||||
13 S A 0 0 0 8448 0.5911 0.74 2280 2357 0 0 1.000 1.000
|
||||
14 S A 0 0 0 21703 7.8267 289.68 2400 2451 0 0 1.000 1.000
|
||||
15 S C 0 0 0 27638 11.0665 419.06 2520 2564 0 0 1.000 1.000
|
||||
16 S A 0 0 0 11761 2.3996 72.96 2640 2695 0 0 1.000 1.000
|
||||
17 S A 0 0 0 12285 2.6856 84.38 2760 2818 0 0 1.000 1.000
|
||||
18 S A 0 0 0 8496 0.6173 1.79 2880 2921 0 0 1.000 1.000
|
||||
19 S A 0 0 0 8466 0.6009 1.13 3000 3081 0 0 1.000 1.000
|
||||
20 S A 0 0 0 16361 4.9106 173.23 3120 3172 0 0 1.000 1.000
|
||||
21 S A 0 0 0 8570 0.6577 3.40 3240 3281 0 0 1.000 1.000
|
||||
22 S A 0 0 0 8690 0.7232 6.02 3360 3413 0 0 1.000 1.000
|
||||
23 S A 0 0 0 8584 0.6653 3.71 3480 3523 0 0 1.000 1.000
|
||||
24 S A 0 0 0 35741 15.4898 595.69 3600 3653 0 0 1.000 1.000
|
||||
25 S A 0 0 0 41497 18.6319 721.16 3720 3772 0 0 1.000 1.000
|
||||
26 S A 0 0 0 23084 8.5806 319.79 3840 3894 0 0 1.000 1.000
|
||||
27 S A 0 0 0 20095 6.9490 254.63 3960 4015 0 0 1.000 1.000
|
||||
28 S A 0 0 0 23096 8.5871 320.05 4080 4138 0 0 1.000 1.000
|
||||
29 S A 0 0 0 23188 8.6374 322.05 4200 4257 0 0 1.000 1.000
|
||||
30 S A 0 0 0 9208 1.0059 17.31 4320 4396 0 0 1.000 1.000
|
||||
31 S A 0 0 0 20005 6.8998 252.67 4440 4495 0 0 1.000 1.000
|
||||
32 S A 0 0 0 25446 9.8700 371.27 4560 4614 0 0 1.000 1.000
|
||||
33 S A 0 0 0 16559 5.0187 177.55 4680 4737 0 0 1.000 1.000
|
||||
34 S A 0 0 0 13113 3.1376 102.43 4800 4865 0 0 1.000 1.000
|
||||
35 S A 0 0 0 60146 28.8121 1127.69 4920 4977 0 0 1.000 1.000
|
||||
36 S O 0 0 0 91039 45.6760 1801.11 5040 5093 0 0 1.000 1.000
|
||||
37 S A 0 0 0 9374 1.0966 20.93 5160 5236 0 0 1.000 1.000
|
||||
38 S A 0 0 0 20797 7.3322 269.93 5280 5331 0 0 1.000 1.000
|
||||
39 S A 0 0 0 8810 0.7887 8.63 5400 5477 0 0 1.000 1.000
|
||||
40 S A 0 0 0 8622 0.6861 4.53 5520 5597 0 0 1.000 1.000
|
||||
41 S A 0 0 0 8663 0.7084 5.43 5640 5681 0 0 1.000 1.000
|
||||
42 S A 0 0 0 8687 0.7215 5.95 5760 5805 0 0 1.000 1.000
|
||||
43 S A 0 0 0 20987 7.4359 274.07 5880 5929 0 0 1.000 1.000
|
||||
44 S A 0 0 0 9483 1.1561 23.30 6000 6048 0 0 1.000 1.000
|
||||
45 S A 0 0 0 27405 10.9394 413.98 6120 6170 0 0 1.000 1.000
|
||||
46 S A 0 0 0 8848 0.8094 9.46 6240 6317 0 0 1.000 1.000
|
||||
47 B A 0 0 0 8541 0.6418 0.00 6480 6536 0 0 1.000 1.000
|
||||
48 D A 0 0 0 26215 10.2898 385.27 6600 6652 0 0 1.000 1.000
|
||||
49 B 0 1 0 8728 0.0000 0.00 6993 6999 0 0 1.000 1.000
|
||||
|
||||
|
||||
-----------------------------------------------------------------------------------------
|
||||
2. 更正的值, 通道: 1
|
||||
|
||||
Pk# Type Cl. CLP Group Digit Conc mAU Start Pos R A Weight Dilution
|
||||
-----------------------------------------------------------------------------------------
|
||||
|
||||
0 B 0 1 0 8414 0.5666 0.00 807 813 0 0 1.000 1.000
|
||||
1 P & 0 0 0 25029 9.7020 362.18 840 899 0 0 1.000 1.000
|
||||
2 D A 0 0 0 25277 9.8384 367.59 960 1017 0 0 1.000 1.000
|
||||
3 N A 0 0 0 8523 0.6265 2.38 1080 1157 0 0 1.000 1.000
|
||||
4 C A 0 0 0 11153 2.0726 59.71 1200 1258 0 0 1.000 1.000
|
||||
5 C A 0 0 0 14445 3.8826 131.47 1320 1380 0 0 1.000 1.000
|
||||
6 C A 0 0 0 18430 6.0737 218.33 1440 1496 0 0 1.000 1.000
|
||||
7 C A 0 0 0 21778 7.9145 291.32 1560 1612 0 0 1.000 1.000
|
||||
8 C A 0 0 0 25674 10.0566 376.24 1680 1739 0 0 1.000 1.000
|
||||
9 N A 0 0 0 8528 0.6293 2.49 1800 1877 0 0 1.000 1.000
|
||||
10 S A 0 0 0 14156 3.7237 125.17 1920 1970 0 0 1.000 1.000
|
||||
11 S A 0 0 0 11538 2.2843 68.10 2040 2086 0 0 1.000 1.000
|
||||
12 S A 0 0 0 12214 2.6559 82.83 2160 2212 0 0 1.000 1.000
|
||||
13 S A 0 0 0 8414 0.5666 0.00 2280 2357 0 0 1.000 1.000
|
||||
14 S A 0 0 0 21516 7.7704 285.61 2400 2451 0 0 1.000 1.000
|
||||
15 S C 0 0 0 27363 10.9853 413.06 2520 2564 0 0 1.000 1.000
|
||||
16 S A 0 0 0 11675 2.3596 71.09 2640 2695 0 0 1.000 1.000
|
||||
17 S A 0 0 0 12186 2.6405 82.22 2760 2818 0 0 1.000 1.000
|
||||
18 S A 0 0 0 8448 0.5853 0.74 2880 2921 0 0 1.000 1.000
|
||||
19 S A 0 0 0 8416 0.5677 0.04 3000 3081 0 0 1.000 1.000
|
||||
20 S A 0 0 0 16175 4.8338 169.18 3120 3172 0 0 1.000 1.000
|
||||
21 S A 0 0 0 8513 0.6210 2.16 3240 3281 0 0 1.000 1.000
|
||||
22 S A 0 0 0 8628 0.6843 4.66 3360 3413 0 0 1.000 1.000
|
||||
23 S A 0 0 0 8522 0.6260 2.35 3480 3523 0 0 1.000 1.000
|
||||
24 S A 0 0 0 35112 15.2459 581.98 3600 3653 0 0 1.000 1.000
|
||||
25 S A 0 0 0 40716 18.3271 704.14 3720 3772 0 0 1.000 1.000
|
||||
26 S A 0 0 0 22686 8.4137 311.11 3840 3894 0 0 1.000 1.000
|
||||
27 S A 0 0 0 19751 6.8000 247.13 3960 4015 0 0 1.000 1.000
|
||||
28 S A 0 0 0 22664 8.4016 310.63 4080 4138 0 0 1.000 1.000
|
||||
29 S A 0 0 0 22739 8.4429 312.26 4200 4257 0 0 1.000 1.000
|
||||
30 S A 0 0 0 9109 0.9487 15.15 4320 4396 0 0 1.000 1.000
|
||||
31 S A 0 0 0 19610 6.7225 244.06 4440 4495 0 0 1.000 1.000
|
||||
32 S A 0 0 0 24886 9.6234 359.07 4560 4614 0 0 1.000 1.000
|
||||
33 S A 0 0 0 16238 4.8685 170.55 4680 4737 0 0 1.000 1.000
|
||||
34 S A 0 0 0 12885 3.0249 97.46 4800 4865 0 0 1.000 1.000
|
||||
35 S A 0 0 0 58461 28.0838 1090.95 4920 4977 0 0 1.000 1.000
|
||||
36 S O 0 0 0 88325 44.5039 1741.95 5040 5093 0 0 1.000 1.000
|
||||
37 S A 0 0 0 9248 1.0252 18.18 5160 5236 0 0 1.000 1.000
|
||||
38 S A 0 0 0 20285 7.0936 258.77 5280 5331 0 0 1.000 1.000
|
||||
39 S A 0 0 0 8697 0.7222 6.17 5400 5477 0 0 1.000 1.000
|
||||
40 S A 0 0 0 8512 0.6205 2.14 5520 5597 0 0 1.000 1.000
|
||||
41 S A 0 0 0 8550 0.6414 2.96 5640 5681 0 0 1.000 1.000
|
||||
42 S A 0 0 0 8570 0.6524 3.40 5760 5805 0 0 1.000 1.000
|
||||
43 S A 0 0 0 20400 7.1568 261.28 5880 5929 0 0 1.000 1.000
|
||||
44 S A 0 0 0 9330 1.0702 19.97 6000 6048 0 0 1.000 1.000
|
||||
45 S A 0 0 0 26535 10.5300 395.01 6120 6170 0 0 1.000 1.000
|
||||
46 S A 0 0 0 8713 0.7310 6.52 6240 6317 0 0 1.000 1.000
|
||||
47 B A 0 0 0 8414 0.5666 0.00 6480 6536 0 0 1.000 1.000
|
||||
48 D A 0 0 0 25277 9.8384 367.59 6600 6652 0 0 1.000 1.000
|
||||
49 B 0 1 0 8414 0.5666 0.00 6993 6999 0 0 1.000 1.000
|
||||
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# @Author: Luxuan
|
||||
# @Date: 2024-05-23 21:50:44
|
||||
# @Last Modified by: Luxuan
|
||||
# @Last Modified time: 2024-05-25 11:07:03
|
||||
|
||||
|
||||
import pyautogui as pag
|
||||
import pywinauto
|
||||
import win32gui
|
||||
import win32con
|
||||
import uiautomation as uiauto
|
||||
import psutil
|
||||
from PIL import ImageGrab,ImageSequence
|
||||
|
||||
class WinUIBase(object):
|
||||
def __init__(self):
|
||||
self.app = None
|
||||
pass
|
||||
|
||||
def launcher(self, app_name, backend='win32',timeout=2):
|
||||
"""
|
||||
:param app_name: app进程名称或者app路径
|
||||
:return:
|
||||
"""
|
||||
pid_list = self._check_processes(app_name)
|
||||
if len(pid_list) == 0:
|
||||
self.app = pywinauto.application.Application(backend=backend).start(app_name, timeout=timeout, retry_interval=2)
|
||||
else:
|
||||
pid = pid_list[0]
|
||||
self.app = pywinauto.application.Application(backend=backend).connect(process=pid, timeout=timeout, retry_interval=2)
|
||||
pass
|
||||
|
||||
def find_window(self, win_title):
|
||||
win = None
|
||||
try:
|
||||
win = self.app.window(title_re=win_title)
|
||||
# self.main_win.maximize()
|
||||
win.wait(wait_for='visible', timeout=3, retry_interval=2)
|
||||
# time.sleep(0.2)
|
||||
return win
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return win
|
||||
pass
|
||||
|
||||
def show_mode(self,win,mode):
|
||||
if mode=="max":
|
||||
win.maximize()
|
||||
elif mode=="min":
|
||||
pass
|
||||
elif mode=="focus":
|
||||
pass
|
||||
elif mode=="top":
|
||||
pass
|
||||
pass
|
||||
|
||||
def get_window(self,name):
|
||||
wins = self.app.windows()
|
||||
win_items = [x for x in wins if x.element_info.name==name]
|
||||
if len(win_items)>0:
|
||||
return win_items[0]
|
||||
return None
|
||||
|
||||
def get_childers(self,control,auto_id = None, class_name = None, name= None):
|
||||
childers = control.descendants()
|
||||
if auto_id:
|
||||
childers = [x for x in childers if x.handle==auto_id]
|
||||
elif class_name:
|
||||
childers = [x for x in childers if x.element_info.class_name==class_name]
|
||||
elif name:
|
||||
childers = [x for x in childers if x.element_info.name==name]
|
||||
|
||||
if len(childers)==1:
|
||||
return childers[0]
|
||||
return childers
|
||||
pass
|
||||
|
||||
def close_popups(self,win,set_show=False):
|
||||
try:
|
||||
popup_hwnd = win.popup_window()
|
||||
if not popup_hwnd or not set_show:
|
||||
return
|
||||
popup_window = self.app.window(handle=popup_hwnd)
|
||||
popup_window.wait(wait_for='visible', timeout=1)
|
||||
popup_window.set_focus()
|
||||
# popup_window.close()
|
||||
popup_window.type_keys("{ENTER}")
|
||||
except Exception as e:
|
||||
print(e)
|
||||
pass
|
||||
|
||||
def _check_processes(self, app_name):
|
||||
pid_list = []
|
||||
processes = psutil.process_iter()
|
||||
for process in processes:
|
||||
try:
|
||||
name = process.name()
|
||||
# conns = process.connections()
|
||||
exe = process.exe()
|
||||
if app_name in name or app_name == exe:
|
||||
pid_list.append(process.pid)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return pid_list
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
||||
|
||||
|
||||
"""
|
||||
pywinauto
|
||||
What is pywinauto — pywinauto 0.6.8 documentation
|
||||
https://pywinauto.readthedocs.io/en/latest/
|
||||
GitHub - 2gis/Winium.Desktop: Winium.Desktop is Selenium Remote WebDriver implementation for automated testing of Windows application based on WinFroms and WPF platforms.
|
||||
https://github.com/2gis/Winium.Desktop
|
||||
|
||||
app2.window(title_re ='Form',class_name_re="WindowsForms10").wait('ready', timeout=10)
|
||||
打印所有子控件
|
||||
print_control_identifiers()
|
||||
|
||||
win.type_keys('{F5}')
|
||||
app = Application(backend='win32').start('notepad.exe')
|
||||
mainwin = app['无标题 - 记事本']
|
||||
mainwin.Edit.type_keys("自动化输入第一行", with_spaces = True)
|
||||
mainwin.child_window(class_name="Edit").type_keys("{ENTER} 自动化输入第二行", with_spaces = True)
|
||||
mainwin.menu_select('文件 -> 保存')
|
||||
app['另存为']['文件名 Edit'].set_text(r'D:\temp\test_pywa\pywa.txt')
|
||||
app['另存为']['保存 Button'].click()
|
||||
app['pywa.txt - 记事本'].type_keys('%FX')
|
||||
|
||||
send_keys('^a^c') # select all (Ctrl+A) and copy to clipboard (Ctrl+C)
|
||||
send_keys('+{INS}') # insert from clipboard (Shift+Ins)
|
||||
send_keys('%{F4}') # close an active window with Alt+F4
|
||||
截图
|
||||
bmp = win.capture_as_image()
|
||||
pywinauto客户端自动化---窗口进行截图 - 测试-安静 - 博客园
|
||||
https://www.cnblogs.com/qican/p/13262198.html
|
||||
|
||||
Python图像库PIL的类Image及其方法介绍_python pil image-CSDN博客
|
||||
https://blog.csdn.net/leemboy/article/details/83792729
|
||||
|
||||
im.getpixel((0,0))
|
||||
Python 查找句柄与控件信息(pywinauto库)_pywinauto edit-CSDN博客
|
||||
https://blog.csdn.net/lylelo/article/details/120214006
|
||||
app[window_title].menu_select("File->open")
|
||||
|
||||
使用pywinauto,如何获取静态文本对象的文本,鉴于父对话框的手柄 - VoidCC
|
||||
http://cn.voidcc.com/question/p-obaazoml-x.html
|
||||
indow_handle = pywinauto.findwindows.find_windows(title = u'My Dialog Name')
|
||||
# 返回应用程序当前顶部窗口,是WindowSpecification对象,可以继续使用对象的方法往下继续查找控件
|
||||
app.top_window()
|
||||
dlg.close() # 关闭界面
|
||||
dlg.minimize() # 最小化界面
|
||||
dlg.maximize() # 最大化界面
|
||||
dlg.restore() # 将窗口恢复为正常大小,比如最小化的让他正常显示在桌面
|
||||
dlg.get_show_state() # 正常0,最大化1,最小化2
|
||||
|
||||
# 移动鼠标
|
||||
mouse.move(coords=(x, y))
|
||||
|
||||
# 指定位置,鼠标左击
|
||||
mouse.click(button='left', coords=(40, 40))
|
||||
|
||||
# 鼠标双击
|
||||
mouse.double_click(button='left', coords=(140, 40))
|
||||
|
||||
# 将属性移动到(140,40)坐标处按下
|
||||
mouse.press(button='left', coords=(140, 40))
|
||||
|
||||
# 将鼠标移动到(300,40)坐标处释放,
|
||||
mouse.release(button='left', coords=(300, 40))
|
||||
|
||||
# 右键单击指定坐标
|
||||
mouse.right_click(coords=(400, 400))
|
||||
|
||||
keyboard.send('enter')
|
||||
keyboard.send('ctrl+v')
|
||||
handle = window.handle
|
||||
|
||||
|
||||
【python句柄获取】——简单明了的获取窗口句柄,并使用句柄操作获取相应内容(全网最详细)_python获取窗口句柄-CSDN博客
|
||||
https://blog.csdn.net/weixin_46625757/article/details/122498299
|
||||
# 通过句柄窗口置顶
|
||||
win32gui.SetWindowPos('句柄值', win32con.HWND_TOPMOST, 0, 0, 0, 0,win32con.SWP_NOMOVE | win32con.SWP_NOACTIVATE | win32con.SWP_NOOWNERZORDER | win32con.SWP_SHOWWINDOW | win32con.SWP_NOSIZE)
|
||||
# 通过句柄取消窗口置顶
|
||||
def set_down(hwnd):
|
||||
win32gui.SetWindowPos(hwnd, win32con.HWND_NOTOPMOST, 0, 0, 0, 0,
|
||||
win32con.SWP_SHOWWINDOW | win32con.SWP_NOSIZE | win32con.SWP_NOMOVE)
|
||||
set_down("句柄值")
|
||||
# 通过句柄将窗口放到最前
|
||||
win32gui.SetForegroundWindow("句柄值")
|
||||
|
||||
# 通过窗口句柄【最大化窗口】
|
||||
win32gui.ShowWindow('句柄值', win32con.SW_MAXIMIZE)
|
||||
|
||||
# 通过窗口句柄【最小化窗口】
|
||||
win32gui.ShowWindow('句柄值', win32con.SW_MINIMIZE)
|
||||
# 通过窗口句柄【关闭当前句柄控件】
|
||||
# 是关闭单个句柄控件,不是关闭整个程序,只能关闭输入的句柄值
|
||||
win32gui.SendMessage('句柄值', win32con.WM_CLOSE)
|
||||
# 在打开此文件所在文件夹并【定位到此文件】
|
||||
FILE = 'C:/Windows/System32/notepad.exe'
|
||||
subprocess.Popen(f'explorer.exe /select,{FILE}', shell=False)
|
||||
#通过窗口标题获取句柄
|
||||
hld = win32gui.FindWindow(None,u"此电脑")
|
||||
"""
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,571 @@
|
|||
|
||||
|
||||
import os,time
|
||||
import pywinauto
|
||||
import pywinauto.controls
|
||||
import pywinauto.keyboard
|
||||
import pywinauto.mouse
|
||||
import win32gui
|
||||
import win32con
|
||||
import pyautogui as pag
|
||||
import uiautomation as uiauto
|
||||
import pyperclip
|
||||
from WinUIBase import WinUIBase
|
||||
import json,datetime
|
||||
|
||||
pag.PAUSE = 0.5
|
||||
|
||||
app_config = {
|
||||
"name": r"C:\Program Files (x86)\SEAL Analytical\AACE 8.03 Beta\aace.exe",
|
||||
"data_dir": r"C:\ProgramData\SEAL Analytical\AACE 8.03 Beta\Data",
|
||||
"login_title": "AACE 登录",
|
||||
"main_title": " AACE for Windows"
|
||||
}
|
||||
|
||||
class AppService(WinUIBase):
|
||||
def __init__(self):
|
||||
self.launcher(app_config["name"])
|
||||
win_login = self.wait_window_show(app_config["login_title"],3)
|
||||
# win_login = self.get_window(app_config["login_title"])
|
||||
if win_login != None:
|
||||
ctrls = win_login.children()
|
||||
btn_oks = [x for x in ctrls if x.element_info.name=="确定"]
|
||||
if len(btn_oks)==1:
|
||||
btn_ok = btn_oks[0]
|
||||
btn_ok.double_click()
|
||||
# time.sleep(3.5)
|
||||
pass
|
||||
pass
|
||||
|
||||
# 等待outtime 秒内窗口出现,出现则返回对应的窗口,否则返回None
|
||||
def wait_window_show(self,title,outtime = 5):
|
||||
start_time = time.time()
|
||||
win_main = None
|
||||
while time.time() - start_time < outtime:
|
||||
win_main = self.get_window(title)
|
||||
if win_main is not None:
|
||||
break
|
||||
time.sleep(0.5)
|
||||
return win_main
|
||||
|
||||
# 等待子窗口显示
|
||||
def wait_child_window_show(self,win_main,title,outtime):
|
||||
start_time = time.time()
|
||||
win_edit = None
|
||||
while time.time() - start_time < outtime:
|
||||
win_edits = self.get_childers(win_main,class_name=title)
|
||||
if win_edits is not None:
|
||||
if isinstance(win_edits,list):
|
||||
if len(win_edits) < 1:
|
||||
print('复制运行打开失败')
|
||||
return -1
|
||||
win_edit = win_edits[0]
|
||||
else:
|
||||
win_edit = win_edits
|
||||
break
|
||||
time.sleep(0.5)
|
||||
return win_edit
|
||||
|
||||
def create(self,args):
|
||||
data = json.loads(args)
|
||||
sample_list = data.get('sampleList',[])
|
||||
num_samples = len(sample_list)
|
||||
TaskTypes = ['氨氮','氨氮&总磷','总磷']
|
||||
tasktype = data.get('taskType')
|
||||
if num_samples < 1 or tasktype not in TaskTypes:
|
||||
print(f'数据错误-{args}')
|
||||
return -1
|
||||
print(f'共-{num_samples}条数据')
|
||||
result = self.click_create_table(tasktype)
|
||||
if result != -1:
|
||||
result = self.start(args)
|
||||
return result
|
||||
|
||||
|
||||
def start(self,args):
|
||||
try:
|
||||
data = json.loads(args)
|
||||
sample_list = data.get('sampleList',[])
|
||||
num_samples = len(sample_list)
|
||||
# TaskTypes = ['氨氮','氨氮&总磷','总磷']
|
||||
# tasktype = data.get('taskType')
|
||||
# if num_samples < 1 or tasktype not in TaskTypes:
|
||||
if num_samples < 1:
|
||||
print(f'数据错误-{args}')
|
||||
return 0
|
||||
except Exception as e:
|
||||
self.loginformation(f'错误-{str(e)}')
|
||||
return 0
|
||||
|
||||
win_main = self.wait_window_show(app_config["main_title"], 5)
|
||||
if win_main == None:
|
||||
return
|
||||
self.read_task_type_list2()
|
||||
self.set_layout_view(win_main)
|
||||
|
||||
try:
|
||||
return self.create_task(win_main,sample_list,"氨氮&总磷")
|
||||
except:
|
||||
return 0
|
||||
pass
|
||||
|
||||
|
||||
def set_layout_view(self,win_main):
|
||||
win_main.set_focus()
|
||||
pag.press(["Alt",'Y',"U"])
|
||||
time.sleep(1)
|
||||
pass
|
||||
|
||||
def create_task(self,win_main,sample_list,task_type="氨氮&总磷"):
|
||||
# 数据处理
|
||||
# 下面是正式开始解析数据,获取到的sorted_unique_positions就是按位置号排序的全部位置
|
||||
unique_positions = set()
|
||||
for sample in sample_list:
|
||||
position = int(sample["position"])
|
||||
unique_positions.add(Convert(position))
|
||||
sorted_unique_positions = sorted(unique_positions)
|
||||
|
||||
# 先执行关闭
|
||||
num_samples = len(sorted_unique_positions)
|
||||
win_edits = self.get_childers(win_main,class_name="TEditAnlDlg")
|
||||
if isinstance(win_edits,list):
|
||||
for win_edit in win_edits:
|
||||
win_edits.set_focus()
|
||||
rect = win_edits.element_info.rectangle
|
||||
pag.click(rect.left+140,rect.top+600)
|
||||
self.close_popups(win_edits)
|
||||
time.sleep(0.5)
|
||||
elif win_edits!=None:
|
||||
win_edits.set_focus()
|
||||
rect = win_edits.element_info.rectangle
|
||||
pag.click(rect.left+140,rect.top+600)
|
||||
self.close_popups(win_edits)
|
||||
time.sleep(0.5)
|
||||
dir_path = os.path.join(app_config["data_dir"],task_type)
|
||||
file_list = os.listdir(dir_path)
|
||||
file_list = [os.path.join(dir_path,str(x)) for x in file_list if str(x).lower().endswith(".run")]
|
||||
file_list = [(x,os.stat(x).st_mtime,time.localtime(os.stat(x).st_mtime)) for x in file_list]
|
||||
file_list.sort(key=lambda x:x[1],reverse=True)
|
||||
last_task = file_list[0]
|
||||
last_task_name = os.path.basename(last_task[0])
|
||||
|
||||
task_type_list = self._show_task_type_view(win_main,"TDirectoryListBox")
|
||||
# listboxItem_data = task_type_list.select(task_type)
|
||||
# pos = task_type_list.item_rect(listboxItem_data)
|
||||
lview = pywinauto.controls.win32_controls.ListBoxWrapper(task_type_list.handle)
|
||||
# texts = lview.item_texts()
|
||||
for dir in ["Data", task_type]:
|
||||
item = lview.select(dir)
|
||||
pos = lview.item_rect(dir)
|
||||
lview.double_click_input(coords=(pos.left+5,pos.top+5))
|
||||
time.sleep(1)
|
||||
# 滚动到最下
|
||||
task_item_list = self._show_task_type_view(win_main,"TMyListView")
|
||||
|
||||
last_item = None
|
||||
for _ in range(2):
|
||||
# 获取列表
|
||||
win_setting_type = self.get_window("设置: 分析")
|
||||
win_main_item = uiauto.ControlFromHandle(win_setting_type.handle)
|
||||
dgv2 = win_main_item.ListControl(ClassName="TMyListView")
|
||||
items = dgv2.GetChildren()
|
||||
|
||||
last_items = [x for x in items if x.Name==last_task_name]
|
||||
if len(last_items)==0:
|
||||
print("在列表中没有找到最新任务")
|
||||
elif len(last_items)==1:
|
||||
rect = last_items[0].BoundingRectangle
|
||||
if rect.left + rect.top!=0:
|
||||
last_item = last_items[0]
|
||||
break
|
||||
pass
|
||||
task_item_list.scroll(direction="down",amount="end")
|
||||
time.sleep(1)
|
||||
rect = last_item.BoundingRectangle
|
||||
last_item_coords=(rect.left+10,rect.top+5)
|
||||
pywinauto.mouse.click(coords=last_item_coords)
|
||||
time.sleep(2)
|
||||
btn_copy_run = self.get_childers(win_setting_type,name="复制运行")
|
||||
btn_copy_run.double_click()
|
||||
# time.sleep(5)
|
||||
# win_edits = self.get_childers(win_main,class_name="TEditAnlDlg")
|
||||
# if isinstance(win_edits,list):
|
||||
# if len(win_edits) < 1:
|
||||
# print('复制运行打开失败')
|
||||
# return -1
|
||||
# win_edit = win_edits[0]
|
||||
# else:
|
||||
# win_edit = win_edits
|
||||
|
||||
win_edit = self.wait_child_window_show(win_main,"TEditAnlDlg",5)
|
||||
if win_edit is None:
|
||||
print('打开复制运行失败')
|
||||
return -1
|
||||
time.sleep(3)
|
||||
case_name = time.strftime("%Y%m%d%H%M%S",time.localtime())+"_auto"
|
||||
pyperclip.copy(f'{case_name}')
|
||||
win_edit.type_keys("^a^v")
|
||||
time.sleep(0.2)
|
||||
|
||||
# 获取盘序按钮并点击.下面代码会报错。先用固定位置
|
||||
# win_edit_tab2 = self.get_childers(win_edit,name="盘序")
|
||||
# win_edit_tab2.click()
|
||||
|
||||
rect = win_edit.element_info.rectangle
|
||||
pag.click(rect.left+70,rect.top+40)
|
||||
time.sleep(0.5)
|
||||
pag.click(rect.left+280,rect.top+590)
|
||||
time.sleep(0.5)
|
||||
|
||||
file_path = r"C:\Users\Lenovo\Videos\wanhua.xlsx"
|
||||
pyperclip.copy(f'{file_path}')
|
||||
pag.hotkey('ctrl', 'v')
|
||||
time.sleep(1)
|
||||
pag.hotkey('enter')
|
||||
time.sleep(0.5)
|
||||
|
||||
win_edits = self.get_childers(win_main,class_name="TEditAnlDlg")
|
||||
#点击盘序
|
||||
pag.click(rect.left+70,rect.top+40)
|
||||
time.sleep(0.5)
|
||||
|
||||
#点击第5行 O 无效的下一行
|
||||
pag.click(rect.left+70,rect.top+165)
|
||||
time.sleep(0.5)
|
||||
# 点击样品按钮 添加样品
|
||||
sample_btn = self.get_childers(win_edits,name="样品")
|
||||
sample_btn.click()
|
||||
sample_btn.click()
|
||||
time.sleep(1)
|
||||
win_samplecup = self.get_window('用于样品的杯')
|
||||
# 找到数量这个文本框,输入数目,杯位无所谓,在外面修改
|
||||
inputs = self.get_childers(win_samplecup,class_name="TSNumberEdit")
|
||||
inputs[1].set_edit_text(num_samples)
|
||||
|
||||
# Alt+确
|
||||
win_samplecup.type_keys("%{确}")
|
||||
time.sleep(0.5)
|
||||
|
||||
# 下面是输入内容,先点击5行图标
|
||||
pag.click(rect.left+70,rect.top+165)
|
||||
time.sleep(0.5)
|
||||
pag.press('right')
|
||||
pag.press('right')
|
||||
|
||||
for pos in sorted_unique_positions:
|
||||
pag.press('space')
|
||||
pag.write(pos)
|
||||
pag.press('tab')
|
||||
|
||||
result = next((x for x in sample_list if (Convert(int(x["position"])) == pos) and int(x["position"]) % 2 != 0), None)
|
||||
if result is not None:
|
||||
pag.press('space')
|
||||
pag.write(result['sampleCode'])
|
||||
print(f"{pos}位置的氨氮值为:{result['sampleCode']}")
|
||||
|
||||
pag.press('tab')
|
||||
pag.press('tab')
|
||||
|
||||
result = next((x for x in sample_list if (Convert(int(x["position"])) == pos) and int(x["position"]) % 2 == 0), None)
|
||||
if result is not None:
|
||||
pag.press('space')
|
||||
pag.write(result['sampleCode'])
|
||||
print(f"{pos}位置的总磷值为:{result['sampleCode']}")
|
||||
|
||||
for _ in range(3):
|
||||
pag.press('tab')
|
||||
|
||||
# for i in range(num_samples):
|
||||
# position = sample_list[i].get('position')
|
||||
# sampleCode = sample_list[i].get('sampleCode')
|
||||
# pag.press('space')
|
||||
# pag.write(position)
|
||||
# # pyperclip.copy(position)
|
||||
# # pag.hotkey('ctrl','v')
|
||||
# pag.press('tab')
|
||||
# pag.press('space')
|
||||
# pag.write(sampleCode)
|
||||
|
||||
# tabcount = 3
|
||||
# match task_type:
|
||||
# case '氨氮':
|
||||
# tabcount = 3
|
||||
# case '氨氮&总磷':
|
||||
# tabcount = 5
|
||||
# case '总磷':
|
||||
# tabcount = 4
|
||||
# case _:
|
||||
# tabcount = 3
|
||||
# for _ in range(tabcount):
|
||||
# pag.press('tab')
|
||||
|
||||
# Alt+确 确定的快捷键
|
||||
win_edit.type_keys("%{确}")
|
||||
# time.sleep(0.5)
|
||||
return 1
|
||||
pass
|
||||
|
||||
def read_task_type_list(self,win_main):
|
||||
listbox_panel = self._show_task_type_view(win_main,"TDirectoryListBox")
|
||||
listboxItem_data = listbox_panel.select("Data")
|
||||
time.sleep(0.1)
|
||||
listboxItem_data.double_click_input(coords=(5,5))
|
||||
time.sleep(0.5)
|
||||
task_type_list = listbox_panel.item_texts()
|
||||
data_index = list(task_type_list).index("Data") + 1
|
||||
task_type_list = task_type_list[data_index:]
|
||||
return task_type_list
|
||||
|
||||
def read_task_type_list2(self):
|
||||
# dir_list = os.listdir(app_config["data_dir"])
|
||||
dir_list = []
|
||||
for root,dirs,file in os.walk(app_config["data_dir"]):
|
||||
dir_list = dirs
|
||||
break
|
||||
pass
|
||||
return dirs
|
||||
pass
|
||||
|
||||
|
||||
def _show_task_type_view(self,win_main,class_name):
|
||||
win_setting_type = self.get_window("设置: 分析")
|
||||
if win_setting_type is None:
|
||||
win_main.set_focus()
|
||||
common_panels = self.get_childers(win_main,class_name="TPanel")
|
||||
rect = common_panels[0].element_info.rectangle
|
||||
coords=(rect.left + 5,rect.top+15)
|
||||
pag.click(coords[0],coords[1])
|
||||
# time.sleep(8)
|
||||
# win_setting_type = self.get_window("设置: 分析")
|
||||
win_setting_type = self.wait_window_show("设置: 分析",8)
|
||||
win_setting_type.set_focus()
|
||||
listbox_panel = self.get_childers(win_setting_type,class_name=class_name)
|
||||
return listbox_panel
|
||||
|
||||
|
||||
# 点击制图,暂时弃用
|
||||
def click_create_table(self, task_type):
|
||||
TaskTypes = ['氨氮','氨氮&总磷','总磷']
|
||||
if task_type not in TaskTypes:
|
||||
print('制图错误')
|
||||
return -1
|
||||
|
||||
# 点击制图按钮
|
||||
win_main = self.get_window(app_config["main_title"])
|
||||
win_main.set_focus()
|
||||
time.sleep(1)
|
||||
create_btn = self.get_childers(win_main,name='制图')
|
||||
if create_btn is None:
|
||||
print('点击制图失败')
|
||||
return -1
|
||||
create_btn.double_click()
|
||||
|
||||
# 弹出的界面点击更改,默认是更改直接点enter
|
||||
win_msg = self.wait_window_show('AACE信息',5)
|
||||
if win_msg is None:
|
||||
print("显示AACE信息失败")
|
||||
return -1
|
||||
|
||||
time.sleep(1)
|
||||
change_btns = self.get_childers(win_msg,name='更改…')
|
||||
change_btn = None
|
||||
if isinstance(change_btns,list):
|
||||
if len(change_btns) < 1:
|
||||
print("未找到更改按钮")
|
||||
return -1
|
||||
else:
|
||||
change_btn = change_btns[0]
|
||||
else:
|
||||
change_btn = change_btns
|
||||
if change_btn is None:
|
||||
print("点击更改...失败")
|
||||
return -1
|
||||
change_btn.double_click()
|
||||
|
||||
#选择分析界面选择 氨氮、氨氮&总磷、总磷 对应的文件
|
||||
win_select_anlysis = self.wait_window_show('选择分析',5)
|
||||
if win_select_anlysis is None:
|
||||
return -1
|
||||
|
||||
# 下面代码为选中对应的模式
|
||||
dir_path = os.path.join(app_config["data_dir"],task_type)
|
||||
file_list = os.listdir(dir_path)
|
||||
file_list = [os.path.join(dir_path,str(x)) for x in file_list if str(x).lower().endswith(".anl")]
|
||||
file_list = [(x,os.stat(x).st_mtime,time.localtime(os.stat(x).st_mtime)) for x in file_list]
|
||||
file_list.sort(key=lambda x:x[1],reverse=True)
|
||||
last_task = file_list[0]
|
||||
last_task_name = os.path.basename(last_task[0])
|
||||
|
||||
win_setting_type = self.get_window("选择分析")
|
||||
if win_setting_type is None:
|
||||
win_main.set_focus()
|
||||
common_panels = self.get_childers(win_main,class_name="TPanel")
|
||||
rect = common_panels[0].element_info.rectangle
|
||||
coords=(rect.left + 5,rect.top+15)
|
||||
pag.click(coords[0],coords[1])
|
||||
# time.sleep(8)
|
||||
# win_setting_type = self.get_window("设置: 分析")
|
||||
win_setting_type = self.wait_window_show("选择分析",8)
|
||||
win_setting_type.set_focus()
|
||||
task_type_list = self.get_childers(win_setting_type,class_name='TDirectoryListBox')
|
||||
lview = pywinauto.controls.win32_controls.ListBoxWrapper(task_type_list.handle)
|
||||
# texts = lview.item_texts()
|
||||
for dir in ["Data", task_type]:
|
||||
item = lview.select(dir)
|
||||
pos = lview.item_rect(dir)
|
||||
lview.double_click_input(coords=(pos.left+5,pos.top+5))
|
||||
time.sleep(1)
|
||||
|
||||
# 点击确认按钮的快捷键
|
||||
win_select_anlysis.type_keys("%{确}")
|
||||
return 1
|
||||
|
||||
# 运行此前设置的分析
|
||||
def run(self,task_type = "氨氮&总磷"):
|
||||
# 点击制图按钮
|
||||
win_main = self.get_window(app_config["main_title"])
|
||||
win_main.set_focus()
|
||||
time.sleep(2)
|
||||
run_btn = self.get_childers(win_main,name='运行')
|
||||
if run_btn is None:
|
||||
return -1
|
||||
run_btn.double_click()
|
||||
#选择分析界面选择 氨氮、氨氮&总磷、总磷 对应的文件
|
||||
win_select_anlysis = self.wait_window_show('运行: 开始',20)
|
||||
if win_select_anlysis is None:
|
||||
print('运行开始界面显示超时')
|
||||
return -1
|
||||
|
||||
# 下面是选择最新的文件
|
||||
dir_path = os.path.join(app_config["data_dir"],task_type)
|
||||
file_list = os.listdir(dir_path)
|
||||
file_list = [os.path.join(dir_path,str(x)) for x in file_list if str(x).lower().endswith(".run")]
|
||||
file_list = [(x,os.stat(x).st_mtime,time.localtime(os.stat(x).st_mtime)) for x in file_list]
|
||||
file_list.sort(key=lambda x:x[1],reverse=True)
|
||||
last_task = file_list[0]
|
||||
last_task_name = os.path.basename(last_task[0])
|
||||
|
||||
task_type_list = self._show_task_type_view_ex(win_main,'运行: 开始',"TDirectoryListBox")
|
||||
# listboxItem_data = task_type_list.select(task_type)
|
||||
# pos = task_type_list.item_rect(listboxItem_data)
|
||||
lview = pywinauto.controls.win32_controls.ListBoxWrapper(task_type_list.handle)
|
||||
# texts = lview.item_texts()
|
||||
for dir in ["Data", task_type]:
|
||||
item = lview.select(dir)
|
||||
pos = lview.item_rect(dir)
|
||||
lview.double_click_input(coords=(pos.left+5,pos.top+5))
|
||||
time.sleep(1)
|
||||
# 滚动到最下
|
||||
task_item_list = self._show_task_type_view_ex(win_main,'运行: 开始',"TMyListView")
|
||||
|
||||
last_item = None
|
||||
for _ in range(2):
|
||||
# 获取列表
|
||||
win_setting_type = self.get_window("运行: 开始")
|
||||
win_main_item = uiauto.ControlFromHandle(win_setting_type.handle)
|
||||
dgv2 = win_main_item.ListControl(ClassName="TMyListView")
|
||||
items = dgv2.GetChildren()
|
||||
|
||||
last_items = [x for x in items if x.Name==last_task_name]
|
||||
if len(last_items)==0:
|
||||
print("在列表中没有找到最新任务")
|
||||
elif len(last_items)==1:
|
||||
rect = last_items[0].BoundingRectangle
|
||||
if rect.left + rect.top!=0:
|
||||
last_item = last_items[0]
|
||||
break
|
||||
pass
|
||||
task_item_list.scroll(direction="down",amount="end")
|
||||
time.sleep(1)
|
||||
rect = last_item.BoundingRectangle
|
||||
last_item_coords=(rect.left+10,rect.top+5)
|
||||
pywinauto.mouse.click(coords=last_item_coords)
|
||||
time.sleep(2)
|
||||
win_select_anlysis.type_keys("%{确}")
|
||||
|
||||
win_start = self.wait_window_show('开始运行',5)
|
||||
if win_start is None:
|
||||
self.loginformation('开始运行界面有误')
|
||||
return -1
|
||||
alarm_checkbox = self.get_childers(win_start,name='声音警报')
|
||||
rect = alarm_checkbox.rectangle()
|
||||
alarm_coords=(rect.left+5,rect.top+5)
|
||||
pywinauto.mouse.click(coords=alarm_coords)
|
||||
time.sleep(1)
|
||||
confirm_coords = (rect.left+5,rect.top+75)
|
||||
pywinauto.mouse.click(coords=confirm_coords)
|
||||
return 1
|
||||
|
||||
# 显示任务类型窗口
|
||||
def _show_task_type_view_ex(self,win_main,title,classname):
|
||||
win_setting_type = self.get_window(title)
|
||||
if win_setting_type is None:
|
||||
win_main.set_focus()
|
||||
common_panels = self.get_childers(win_main,class_name="TPanel")
|
||||
rect = common_panels[0].element_info.rectangle
|
||||
coords=(rect.left + 5,rect.top+15)
|
||||
pag.click(coords[0],coords[1])
|
||||
# time.sleep(8)
|
||||
# win_setting_type = self.get_window("设置: 分析")
|
||||
win_setting_type = self.wait_window_show(title,8)
|
||||
win_setting_type.set_focus()
|
||||
listbox_panel = self.get_childers(win_setting_type,class_name=classname)
|
||||
return listbox_panel
|
||||
|
||||
def loginformation(self,content):
|
||||
print(f'{datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}:{content}')
|
||||
|
||||
|
||||
def is_finished(self):
|
||||
win_main = self.get_window("AACE信息")
|
||||
if win_main is None:
|
||||
return 0
|
||||
|
||||
alram_infos = self.get_childers(win_main,name='声音报警')
|
||||
alarm_info = None
|
||||
result = 0
|
||||
if isinstance(alram_infos,list):
|
||||
if len(alram_infos) > 0:
|
||||
alarm_info = alram_infos[0]
|
||||
elif alram_infos is not None:
|
||||
alarm_info = alram_infos
|
||||
if alarm_info is None:
|
||||
result = 0
|
||||
else:
|
||||
#win_main.get_properties()
|
||||
if win_main.is_visible():
|
||||
result = 1
|
||||
return result
|
||||
|
||||
def createThenStart(self,args):
|
||||
if self.start(args) != 1:
|
||||
return 0
|
||||
return self.run()
|
||||
|
||||
def Convert(self,number):
|
||||
if number % 2 == 0:
|
||||
number = number - 1
|
||||
col = number % 6 // 2
|
||||
row = number // 6
|
||||
return 46 + 15 * col + row * 2
|
||||
|
||||
def Convert(number):
|
||||
if number % 2 == 0:
|
||||
number = number - 1
|
||||
col = number % 6 // 2
|
||||
row = number // 6
|
||||
return 46 + 15 * col + row * 2
|
||||
|
||||
if __name__ == "__main__":
|
||||
# # taskType 为: 氨氮、氨氮&总磷、总磷 3,5,4
|
||||
#json_data = {"taskType":"氨氮","sampleList":[{"sampleCode":"11","position":"1"},{"sampleCode":"12","position":"3"}]}
|
||||
#appService.click_create_table("氨氮")
|
||||
#appService.start(paras)
|
||||
#appService.run("氨氮")
|
||||
# print(appService.is_finished())
|
||||
#pass
|
||||
appService = AppService()
|
||||
json_data = {"sampleList":[{"sampleCode":"111","position":"1"},{"sampleCode":"112","position":"2"},{"sampleCode":"113","position":"7"},{"sampleCode":"114","position":"20"}]}
|
||||
paras = json.dumps(json_data)
|
||||
appService.createThenStart(paras)
|
||||
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
import mimetypes
|
||||
import time
|
||||
from watchdog.observers import Observer
|
||||
from watchdog.events import FileSystemEventHandler
|
||||
import http.client
|
||||
|
||||
# 服务器的 IP 地址和端口号
|
||||
server = "192.168.6.11"
|
||||
server_port = 8080
|
||||
# 接口路径
|
||||
# server_url = "/Interface/Result/Create"
|
||||
server_url = "/wanhua-service/equipment/external/checkResult"
|
||||
|
||||
class Watcher:
|
||||
def __init__(self, directory_to_watch):
|
||||
self.observer = Observer()
|
||||
self.directory_to_watch = directory_to_watch
|
||||
|
||||
def run(self):
|
||||
print(f'开始监听文件夹{self.directory_to_watch}')
|
||||
event_handler = Handler()
|
||||
self.observer.schedule(event_handler, self.directory_to_watch, recursive=True)
|
||||
self.observer.start()
|
||||
try:
|
||||
while True:
|
||||
time.sleep(1)
|
||||
except KeyboardInterrupt:
|
||||
self.observer.stop()
|
||||
finally:
|
||||
self.observer.join()
|
||||
|
||||
def join(self):
|
||||
self.observer.join()
|
||||
|
||||
|
||||
|
||||
class Handler(FileSystemEventHandler):
|
||||
@staticmethod
|
||||
def on_created(event):
|
||||
if not event.is_directory:
|
||||
if event.src_path.endswith('.pdf') or event.src_path.endswith('.csv') or event.src_path.endswith('.xlsx'):
|
||||
print(f"监控到---{event.src_path}---已被创建")
|
||||
time.sleep(1)
|
||||
try:
|
||||
# 构建multipart/form-data请求体
|
||||
boundary = 'Boundary-0123456789'
|
||||
headers = {
|
||||
'Content-Type': f'multipart/form-data; boundary={boundary}'
|
||||
}
|
||||
# 确定文件的MIME类型
|
||||
mime_type, _ = mimetypes.guess_type(event.src_path)
|
||||
|
||||
# 构建请求体
|
||||
body = []
|
||||
body.append(f'--{boundary}')
|
||||
body.append(
|
||||
f'Content-Disposition: form-data; name="file"; filename="{event.src_path}"')
|
||||
body.append(f'Content-Type: {mime_type}')
|
||||
body.append('')
|
||||
with open(event.src_path, mode='r', newline='', encoding='gb2312', errors='ignore') as file:
|
||||
body.append(file.read())
|
||||
body.append(f'--{boundary}--')
|
||||
body.append('')
|
||||
# 将请求体转换为字节串
|
||||
body_bytes = '\r\n'.join(body).encode('utf-8')
|
||||
|
||||
# 创建 HTTP 连接对象
|
||||
conn = http.client.HTTPConnection(server, server_port)
|
||||
# 发送POST请求
|
||||
conn.request("POST", f"{server_url}?deviceKey=titration&passback=false", body=body_bytes, headers=headers)
|
||||
|
||||
# 获取响应
|
||||
response = conn.getresponse()
|
||||
|
||||
# 读取响应内容
|
||||
response_data = response.read()
|
||||
|
||||
# 检查响应状态码
|
||||
if response.status == 200:
|
||||
print('数据发送成功')
|
||||
print(response_data.decode()) # 打印服务器的响应内容
|
||||
else:
|
||||
print('数据发送失败')
|
||||
print(response.status) # 打印错误状态码
|
||||
print(response.reason) # 打印错误状态码
|
||||
print(response_data.decode()) # 打印错误状态码
|
||||
# break # 找到第一个非空行后终止遍历
|
||||
except Exception as e:
|
||||
print(f"发生异常: {e}")
|
||||
finally:
|
||||
# 关闭连接
|
||||
conn.close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# logger.info(f"当前用户名: {getuser()}")
|
||||
w = Watcher(r"D:\src\logs")
|
||||
w.run()
|
||||
|
|
@ -0,0 +1,236 @@
|
|||
# import socket
|
||||
# import threading
|
||||
# import aacecontrol
|
||||
# import ctypes,win32con,win32gui,sys,json
|
||||
# import logging
|
||||
# # import file_script
|
||||
|
||||
|
||||
# IpAddress = '127.0.0.1'
|
||||
# FilePath = 'D:\\MegaSoft\\Scripts'
|
||||
# Port = 2016
|
||||
# # device = md.MultiWinDevice("multiWin")
|
||||
# device = aacecontrol.AppService()
|
||||
# # 定义互斥量名称
|
||||
# mutex_name = "aaca_mutex"
|
||||
|
||||
|
||||
# def handle_client(client_socket,addr):
|
||||
# device.loginformation(f'监听{addr}的数据')
|
||||
# while True:
|
||||
# try:
|
||||
# # 接收客户端发送的数据
|
||||
# data = client_socket.recv(2048)
|
||||
# if not data:
|
||||
# device.loginformation(f'{addr}-接收到空数据')
|
||||
# break
|
||||
# # # 处理接收到的数据
|
||||
# # device.loginformation(f"Received from {client_socket.getpeername()}: {data.decode('utf-8')}")
|
||||
# datadecode = data.decode('utf-8')
|
||||
# command = datadecode.partition(':')[0] # 只分割一次
|
||||
# paras = datadecode.partition(':')[2]
|
||||
# result = -1
|
||||
|
||||
# if 'makeGraph' in command:
|
||||
# command = 'makeGraph'
|
||||
# device.loginformation(f'---收到制图指令 {datadecode}---')
|
||||
# result = device.click_create_table(paras)
|
||||
# elif 'operate' in command:
|
||||
# command = 'operate'
|
||||
# device.loginformation(f'---收到创建任务指令 {datadecode}---')
|
||||
# result = device.start(paras)
|
||||
# elif 'createTask' in command:
|
||||
# command = 'createTask'
|
||||
# device.loginformation(f'---收到制图创建任务命令 {datadecode}---')
|
||||
# result = device.create(paras)
|
||||
# elif 'start' in command:
|
||||
# command = 'start'
|
||||
# device.loginformation(f'---收到启动命令 {datadecode}---')
|
||||
# result = device.run(paras)
|
||||
# elif 'status' in command:
|
||||
# device.loginformation(f'---收到查询状态命令 {datadecode}---')
|
||||
# result = 2
|
||||
# if device.is_finished():
|
||||
# result = 1
|
||||
# else:
|
||||
# command = '未知命令'
|
||||
# device.loginformation('---未知命令---')
|
||||
|
||||
# reponse_txt = command + ':' + str(result) + '\n'
|
||||
# client_socket.send(reponse_txt.encode('utf-8'))
|
||||
# device.loginformation(f'---返回-{reponse_txt}---')
|
||||
# except:
|
||||
# device.loginformation(f'{addr}-接收数据异常')
|
||||
# client_socket.close()
|
||||
# return
|
||||
# # 关闭连接
|
||||
# device.loginformation(f'{addr}-连接断开')
|
||||
# client_socket.close()
|
||||
|
||||
# def start_server():
|
||||
# server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
# server.bind((IpAddress, Port))
|
||||
# server.listen(20)
|
||||
# device.loginformation(f"Server listening on port {IpAddress}:{Port}...")
|
||||
# try:
|
||||
# while True:
|
||||
# client_socket, addr = server.accept()
|
||||
# device.loginformation(f"Accepted connection from {addr}")
|
||||
# # 启动一个新线程来处理客户端请求
|
||||
# client_handler = threading.Thread(target=handle_client, args=(client_socket,addr))
|
||||
# client_handler.start()
|
||||
# except:
|
||||
# print('服务结束了。。。')
|
||||
# finally:
|
||||
# ctypes.windll.kernel32.CloseHandle(mutex)
|
||||
|
||||
# def message_box(title, message, type=win32con.MB_OK):
|
||||
# """
|
||||
# 弹出一个消息框
|
||||
# :param title: 消息框的标题
|
||||
# :param message: 消息框显示的消息
|
||||
# :param type: 消息框的类型,例如MB_OK, MB_ICONERROR等
|
||||
# :return: 用户点击的消息框按钮的标识符
|
||||
# """
|
||||
# return win32gui.MessageBox(None, message, title, type)
|
||||
|
||||
# if __name__ == "__main__":
|
||||
# # 定义互斥锁名称,可以是任意字符串
|
||||
# mutex = ctypes.windll.kernel32.CreateMutexW(None, False, mutex_name)
|
||||
# # 检查互斥量是否已经存在
|
||||
# if ctypes.windll.kernel32.GetLastError() == 183: # ERROR_ALREADY_EXISTS
|
||||
# message_box("提醒", "脚本正在运行中,请点击确定关闭。", win32con.MB_ICONWARNING)
|
||||
# sys.exit(0)
|
||||
|
||||
# ctypes.windll.kernel32.SetThreadExecutionState(0x80000002) # 确保桌面不息屏
|
||||
|
||||
# server_thread = threading.Thread(target=start_server)
|
||||
# server_thread.start()
|
||||
|
||||
# # w = file_script.Watcher(FilePath)
|
||||
# # file_thread = threading.Thread(target=w.run)
|
||||
# # file_thread.start()
|
||||
|
||||
|
||||
import ctypes
|
||||
import socket
|
||||
import sys
|
||||
import threading
|
||||
import win32con
|
||||
import win32gui
|
||||
from file_script import Watcher
|
||||
import aacecontrol
|
||||
|
||||
|
||||
IpAddress = '127.0.0.1'
|
||||
FilePath = 'D:\\MegaSoft\\Scripts'
|
||||
Port = 2016
|
||||
device = aacecontrol.AppService()
|
||||
# 定义互斥量名称
|
||||
mutex_name = "aaca_mutex"
|
||||
|
||||
def handle_client(client, addr):
|
||||
while True:
|
||||
try:
|
||||
data = client.recv(2048)
|
||||
if not data:
|
||||
device.loginformation("接收数据异常")
|
||||
break
|
||||
datadecode = data.decode('utf-8')
|
||||
device.loginformation(f"接收到---{client.getpeername()}---数据---{datadecode}")
|
||||
result = -1
|
||||
command = datadecode.partition(':')[0] # 只分割一次
|
||||
paras = datadecode.partition(':')[2] # 返回包含分隔符
|
||||
|
||||
# if 'makeGraph' in command:
|
||||
# command = 'makeGraph'
|
||||
# device.loginformation(f'---收到制图指令 {datadecode}---')
|
||||
# result = device.click_create_table(paras)
|
||||
# elif 'operate' in command:
|
||||
# command = 'operate'
|
||||
# device.loginformation(f'---收到创建任务指令 {datadecode}---')
|
||||
# result = device.start(paras)
|
||||
if 'createTask' in command:
|
||||
command = 'createTask'
|
||||
device.loginformation(f'收到创建任务并执行命令 {datadecode}')
|
||||
result = device.createThenStart(paras)
|
||||
# elif 'start' in command:
|
||||
# command = 'start'
|
||||
# device.loginformation(f'---收到启动命令 {datadecode}---')
|
||||
# result = device.run(paras)
|
||||
elif 'status' in command:
|
||||
device.loginformation(f'收到查询状态命令 {datadecode}')
|
||||
result = 2
|
||||
if device.is_finished():
|
||||
result = 0
|
||||
else:
|
||||
command = '未知命令'
|
||||
device.loginformation('未知命令')
|
||||
|
||||
response_txt = command + ':' + str(result) + '\n'
|
||||
device.loginformation(f'返回:{command}:{str(result)}')
|
||||
client.send(response_txt.encode('utf-8'))
|
||||
except:
|
||||
device.loginformation(f'{addr}通讯异常')
|
||||
break
|
||||
# 关闭连接
|
||||
device.loginformation(f'关闭{addr}连接')
|
||||
client.close()
|
||||
|
||||
def message_box(title, message, type=win32con.MB_OK):
|
||||
"""
|
||||
弹出一个消息框
|
||||
:param title: 消息框的标题
|
||||
:param message: 消息框显示的消息
|
||||
:param type: 消息框的类型,例如MB_OK, MB_ICONERROR等
|
||||
:return: 用户点击的消息框按钮的标识符
|
||||
"""
|
||||
return win32gui.MessageBox(None, message, title, type)
|
||||
|
||||
|
||||
class TCPThread(threading.Thread):
|
||||
def run(self):
|
||||
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
server.bind((IpAddress, Port))
|
||||
server.listen(20)
|
||||
device.loginformation(f"服务端---{IpAddress}---{Port}---启动")
|
||||
connected_clients = 0
|
||||
try:
|
||||
while True:
|
||||
client, addr = server.accept()
|
||||
connected_clients = connected_clients + 1
|
||||
device.loginformation(f"客户端---{addr}---已连接,已连接客户端数量:{connected_clients}")
|
||||
client_handle = threading.Thread(target=handle_client, args=(client,addr))
|
||||
client_handle.start()
|
||||
except Exception as e:
|
||||
device.loginformation(f"{str(e)}服务端正在关闭...")
|
||||
server.close()
|
||||
device.loginformation("服务端已关闭")
|
||||
finally:
|
||||
# 释放互斥量
|
||||
ctypes.windll.kernel32.CloseHandle(mutex)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 定义互斥锁名称,可以是任意字符串
|
||||
mutex = ctypes.windll.kernel32.CreateMutexW(None, False, mutex_name)
|
||||
# 检查互斥量是否已经存在
|
||||
if ctypes.windll.kernel32.GetLastError() == 183: # ERROR_ALREADY_EXISTS
|
||||
message_box("提醒", "脚本正在运行中,请点击确定关闭。", win32con.MB_ICONWARNING)
|
||||
sys.exit(0)
|
||||
|
||||
ctypes.windll.kernel32.SetThreadExecutionState(0x80000002)
|
||||
|
||||
tcp_thread = TCPThread()
|
||||
tcp_thread.start()
|
||||
|
||||
# 创建线程
|
||||
watcher = Watcher(FilePath)
|
||||
watcher_thread = threading.Thread(target=watcher.run)
|
||||
watcher_thread.start()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 130 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
|
|
@ -0,0 +1,21 @@
|
|||
## 通讯协议TCP,控制脚本作为server端
|
||||
192.168.6.**:2016 (未插网线ip待定)
|
||||
|
||||
|
||||
# 客户做之前需要点击制图-氨氮&总磷 确认制图正确
|
||||
|
||||
## 设置分析并启动(客户自己确认已制图完成):
|
||||
发送:createTask:{"sampleList":[
|
||||
{"sampleCode":"111","position":"1"},
|
||||
{"sampleCode":"112","position":"2"}]
|
||||
}
|
||||
<br/>返回:1成功 0失败
|
||||
|
||||
注: position给料盘实际编号就行,仪器需要的类型及位置通过脚本来自行判断,position位置为1~48,流动注射仪未开启会失败返回0
|
||||
|
||||
## 状态查询命令:
|
||||
发送:status
|
||||
<br/>返回: 0:就绪 2:完成
|
||||
<br/>注:完成之后有个弹窗,只能通过该弹窗判断是否完成任务,没有弹窗时无法区分是就绪还是运行中
|
||||
|
||||
|
||||
Loading…
Reference in New Issue