Compare commits

...

No commits in common. "main" and "master" have entirely different histories.
main ... master

20 changed files with 1334 additions and 165 deletions

162
.gitignore vendored
View File

@ -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/

View File

@ -1,3 +0,0 @@
# AACA
流动注射脚本

3
Scripts/.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

View File

@ -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>

View File

@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>

7
Scripts/.idea/misc.xml Normal file
View File

@ -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>

View File

@ -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>

20
Scripts/.vscode/settings.json vendored Normal file
View File

@ -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
}
]
}

View File

@ -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 ->

121
Scripts/Data/1.txt Normal file
View File

@ -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

209
Scripts/WinUIBase.py Normal file
View File

@ -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))
# 将属性移动到14040坐标处按下
mouse.press(button='left', coords=(140, 40))
# 将鼠标移动到30040坐标处释放
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.

571
Scripts/aacecontrol.py Normal file
View File

@ -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)

98
Scripts/file_script.py Normal file
View File

@ -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()

236
Scripts/service.py Normal file
View File

@ -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()

BIN
Scripts/temp.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

BIN
Scripts/temp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

21
readme.md Normal file
View File

@ -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/>注:完成之后有个弹窗,只能通过该弹窗判断是否完成任务,没有弹窗时无法区分是就绪还是运行中