gravity-controller-operator 2.0.2__tar.gz → 2.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/LICENSE +18 -18
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/PKG-INFO +124 -115
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/README.md +101 -101
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/__init__.py +0 -0
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/controller_factory.py +29 -28
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/controllers/__init__.py +0 -0
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/controllers/arm_k210.py +54 -47
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/controllers/emulator_contr.py +36 -36
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/controllers/moxa.py +80 -80
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/controllers/netping_relay.py +76 -76
- gravity_controller_operator-2.3.0/gravity_controller_operator/controllers/sigur.py +52 -0
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/controllers/tests/__init__.py +0 -0
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/controllers/tests/test_moxa_controller.py +31 -31
- gravity_controller_operator-2.3.0/gravity_controller_operator/controllers/tests/test_wb_mr6lv_tcp.py +129 -0
- gravity_controller_operator-2.3.0/gravity_controller_operator/controllers/wb_mr6lv.py +128 -0
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/controllers_super.py +121 -105
- gravity_controller_operator-2.3.0/gravity_controller_operator/diagnostics_cli.py +267 -0
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/docs/__init__.py +0 -0
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/exceptions.py +8 -8
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/main.py +57 -47
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/tests/__init__.py +0 -0
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator/tests/main_tests.py +19 -19
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator.egg-info/PKG-INFO +124 -115
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator.egg-info/SOURCES.txt +2 -0
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/setup.cfg +4 -4
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/setup.py +21 -21
- gravity_controller_operator-2.0.2/gravity_controller_operator/controllers/sigur.py +0 -75
- gravity_controller_operator-2.0.2/gravity_controller_operator/controllers/wb_mr6lv.py +0 -63
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator.egg-info/dependency_links.txt +0 -0
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator.egg-info/requires.txt +0 -0
- {gravity_controller_operator-2.0.2 → gravity_controller_operator-2.3.0}/gravity_controller_operator.egg-info/top_level.txt +0 -0
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
Copyright (c) 2018 The Python Packaging Authority
|
|
2
|
-
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
-
in the Software without restriction, including without limitation the rights
|
|
6
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
-
furnished to do so, subject to the following conditions:
|
|
9
|
-
|
|
10
|
-
The above copyright notice and this permission notice shall be included in all
|
|
11
|
-
copies or substantial portions of the Software.
|
|
12
|
-
|
|
13
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1
|
+
Copyright (c) 2018 The Python Packaging Authority
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
19
|
SOFTWARE.
|
|
@@ -1,115 +1,124 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
2
|
-
Name: gravity_controller_operator
|
|
3
|
-
Version: 2.0
|
|
4
|
-
Summary: SDK предоставляющий универсальный интерфейс для работы со многими промышленными контроллерами ввода-вывода (количество расширяемо)
|
|
5
|
-
Author: PunchyArchy
|
|
6
|
-
Author-email: ksmdrmvscthny@gmail.com
|
|
7
|
-
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Classifier: Operating System :: OS Independent
|
|
9
|
-
Requires-Python: >=3.7
|
|
10
|
-
Description-Content-Type: text/markdown
|
|
11
|
-
License-File: LICENSE
|
|
12
|
-
Requires-Dist: pyModbusTCP
|
|
13
|
-
Requires-Dist: pymodbus==3.6.9
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gravity_controller_operator
|
|
3
|
+
Version: 2.3.0
|
|
4
|
+
Summary: SDK предоставляющий универсальный интерфейс для работы со многими промышленными контроллерами ввода-вывода (количество расширяемо)
|
|
5
|
+
Author: PunchyArchy
|
|
6
|
+
Author-email: ksmdrmvscthny@gmail.com
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Requires-Python: >=3.7
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: pyModbusTCP
|
|
13
|
+
Requires-Dist: pymodbus==3.6.9
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: author-email
|
|
16
|
+
Dynamic: classifier
|
|
17
|
+
Dynamic: description
|
|
18
|
+
Dynamic: description-content-type
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
Dynamic: requires-dist
|
|
21
|
+
Dynamic: requires-python
|
|
22
|
+
Dynamic: summary
|
|
23
|
+
|
|
24
|
+
# Gravity Controller Operator
|
|
25
|
+
|
|
26
|
+
Модуль для унифицированной работы с промышленными контроллерами (реле, дискретные входы и т.д.). Позволяет взаимодействовать с различными устройствами через единый интерфейс.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 🚀 Поддерживаемые контроллеры
|
|
31
|
+
|
|
32
|
+
- **EmulatorController** — заглушка для тестов
|
|
33
|
+
- **ARMK210Controller** — Modbus TCP
|
|
34
|
+
- **WBMR6LV** — Modbus RTU
|
|
35
|
+
- **NetPing2Controller** — HTTP API
|
|
36
|
+
- **Sigur** — доступ через TCP (СКУД)
|
|
37
|
+
- **MoxaE1214** — REST API (vdn.dac.v1)
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 🧩 Архитектура
|
|
42
|
+
|
|
43
|
+
### 🧠 Интерфейсы:
|
|
44
|
+
|
|
45
|
+
- `DIInterface`: чтение дискретных входов
|
|
46
|
+
- `RelayInterface`: чтение/управление релейными выходами
|
|
47
|
+
- `ControllerInterface`: объединяет оба
|
|
48
|
+
|
|
49
|
+
Все интерфейсы наследуют `SoftStateMixin`, в котором реализовано хранение состояния точек (`state`, `changed`, `addr`).
|
|
50
|
+
|
|
51
|
+
### 🛠 Контроллер
|
|
52
|
+
Каждый контроллер реализует:
|
|
53
|
+
```python
|
|
54
|
+
self.interface = ControllerInterface(di_interface=..., relay_interface=...)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### 🧪 Обёртки:
|
|
58
|
+
|
|
59
|
+
- `ControllerOperator` — отвечает за автоматическое обновление, mutex-безопасность и удобный API
|
|
60
|
+
- `ControllerCreator` — фабрика создания контроллеров по имени модели (см. `controller_factory.py`)
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 🧪 Как использовать
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from gravity_controller_operator.controllers.moxa import MoxaE1214
|
|
68
|
+
from gravity_controller_operator.controller_operator import ControllerOperator
|
|
69
|
+
|
|
70
|
+
moxa = MoxaE1214("192.168.60.103")
|
|
71
|
+
operator = ControllerOperator(moxa)
|
|
72
|
+
|
|
73
|
+
print(operator.get_points())
|
|
74
|
+
operator.change_relay_state(0, 1) # включить реле 0
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 🔬 Тестирование
|
|
80
|
+
|
|
81
|
+
Установка:
|
|
82
|
+
```bash
|
|
83
|
+
pip install pytest
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Запуск:
|
|
87
|
+
```bash
|
|
88
|
+
pytest gravity_controller_operator/tests/
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## 📦 Добавление нового контроллера
|
|
94
|
+
|
|
95
|
+
1. Реализуй `YourControllerDI` и `YourControllerRelay`, наследуя `DIInterface`, `RelayInterface`
|
|
96
|
+
2. Создай `YourController`, в котором:
|
|
97
|
+
```python
|
|
98
|
+
self.interface = ControllerInterface(di_interface=..., relay_interface=...)
|
|
99
|
+
```
|
|
100
|
+
3. Добавь контроллер в `AVAILABLE_CONTROLLERS` в `controller_factory.py`
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## 📁 Структура
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
controllers_super.py # Базовые интерфейсы
|
|
108
|
+
controllers/ # Реализации контроллеров
|
|
109
|
+
controller_operator.py # Обёртка ControllerOperator ✅
|
|
110
|
+
controller_factory.py # AVAILABLE_CONTROLLERS + фабрика ✅
|
|
111
|
+
exceptions.py # Кастомные исключения ✅
|
|
112
|
+
tests/ # Тесты
|
|
113
|
+
README.md
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## 🤝 Контакты
|
|
119
|
+
|
|
120
|
+
- 📧 Email: ksmdrmvstchny@gmail.com
|
|
121
|
+
- 💬 Telegram: [@PunchyArchy](https://t.me/PunchyArchy)
|
|
122
|
+
- 📞 Phone: +7 996 294-75-95
|
|
123
|
+
|
|
124
|
+
Проект поддерживается Артуром (PunchyArchy, Qodex)
|
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
# Gravity Controller Operator
|
|
2
|
-
|
|
3
|
-
Модуль для унифицированной работы с промышленными контроллерами (реле, дискретные входы и т.д.). Позволяет взаимодействовать с различными устройствами через единый интерфейс.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## 🚀 Поддерживаемые контроллеры
|
|
8
|
-
|
|
9
|
-
- **EmulatorController** — заглушка для тестов
|
|
10
|
-
- **ARMK210Controller** — Modbus TCP
|
|
11
|
-
- **WBMR6LV** — Modbus RTU
|
|
12
|
-
- **NetPing2Controller** — HTTP API
|
|
13
|
-
- **Sigur** — доступ через TCP (СКУД)
|
|
14
|
-
- **MoxaE1214** — REST API (vdn.dac.v1)
|
|
15
|
-
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
## 🧩 Архитектура
|
|
19
|
-
|
|
20
|
-
### 🧠 Интерфейсы:
|
|
21
|
-
|
|
22
|
-
- `DIInterface`: чтение дискретных входов
|
|
23
|
-
- `RelayInterface`: чтение/управление релейными выходами
|
|
24
|
-
- `ControllerInterface`: объединяет оба
|
|
25
|
-
|
|
26
|
-
Все интерфейсы наследуют `SoftStateMixin`, в котором реализовано хранение состояния точек (`state`, `changed`, `addr`).
|
|
27
|
-
|
|
28
|
-
### 🛠 Контроллер
|
|
29
|
-
Каждый контроллер реализует:
|
|
30
|
-
```python
|
|
31
|
-
self.interface = ControllerInterface(di_interface=..., relay_interface=...)
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
### 🧪 Обёртки:
|
|
35
|
-
|
|
36
|
-
- `ControllerOperator` — отвечает за автоматическое обновление, mutex-безопасность и удобный API
|
|
37
|
-
- `ControllerCreator` — фабрика создания контроллеров по имени модели (см. `controller_factory.py`)
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## 🧪 Как использовать
|
|
42
|
-
|
|
43
|
-
```python
|
|
44
|
-
from gravity_controller_operator.controllers.moxa import MoxaE1214
|
|
45
|
-
from gravity_controller_operator.controller_operator import ControllerOperator
|
|
46
|
-
|
|
47
|
-
moxa = MoxaE1214("192.168.60.103")
|
|
48
|
-
operator = ControllerOperator(moxa)
|
|
49
|
-
|
|
50
|
-
print(operator.get_points())
|
|
51
|
-
operator.change_relay_state(0, 1) # включить реле 0
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
## 🔬 Тестирование
|
|
57
|
-
|
|
58
|
-
Установка:
|
|
59
|
-
```bash
|
|
60
|
-
pip install pytest
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Запуск:
|
|
64
|
-
```bash
|
|
65
|
-
pytest gravity_controller_operator/tests/
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## 📦 Добавление нового контроллера
|
|
71
|
-
|
|
72
|
-
1. Реализуй `YourControllerDI` и `YourControllerRelay`, наследуя `DIInterface`, `RelayInterface`
|
|
73
|
-
2. Создай `YourController`, в котором:
|
|
74
|
-
```python
|
|
75
|
-
self.interface = ControllerInterface(di_interface=..., relay_interface=...)
|
|
76
|
-
```
|
|
77
|
-
3. Добавь контроллер в `AVAILABLE_CONTROLLERS` в `controller_factory.py`
|
|
78
|
-
|
|
79
|
-
---
|
|
80
|
-
|
|
81
|
-
## 📁 Структура
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
controllers_super.py # Базовые интерфейсы
|
|
85
|
-
controllers/ # Реализации контроллеров
|
|
86
|
-
controller_operator.py # Обёртка ControllerOperator ✅
|
|
87
|
-
controller_factory.py # AVAILABLE_CONTROLLERS + фабрика ✅
|
|
88
|
-
exceptions.py # Кастомные исключения ✅
|
|
89
|
-
tests/ # Тесты
|
|
90
|
-
README.md
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
## 🤝 Контакты
|
|
96
|
-
|
|
97
|
-
- 📧 Email: ksmdrmvstchny@gmail.com
|
|
98
|
-
- 💬 Telegram: [@PunchyArchy](https://t.me/PunchyArchy)
|
|
99
|
-
- 📞 Phone: +7 996 294-75-95
|
|
100
|
-
|
|
101
|
-
Проект поддерживается Артуром (PunchyArchy, Qodex)
|
|
1
|
+
# Gravity Controller Operator
|
|
2
|
+
|
|
3
|
+
Модуль для унифицированной работы с промышленными контроллерами (реле, дискретные входы и т.д.). Позволяет взаимодействовать с различными устройствами через единый интерфейс.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🚀 Поддерживаемые контроллеры
|
|
8
|
+
|
|
9
|
+
- **EmulatorController** — заглушка для тестов
|
|
10
|
+
- **ARMK210Controller** — Modbus TCP
|
|
11
|
+
- **WBMR6LV** — Modbus RTU
|
|
12
|
+
- **NetPing2Controller** — HTTP API
|
|
13
|
+
- **Sigur** — доступ через TCP (СКУД)
|
|
14
|
+
- **MoxaE1214** — REST API (vdn.dac.v1)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 🧩 Архитектура
|
|
19
|
+
|
|
20
|
+
### 🧠 Интерфейсы:
|
|
21
|
+
|
|
22
|
+
- `DIInterface`: чтение дискретных входов
|
|
23
|
+
- `RelayInterface`: чтение/управление релейными выходами
|
|
24
|
+
- `ControllerInterface`: объединяет оба
|
|
25
|
+
|
|
26
|
+
Все интерфейсы наследуют `SoftStateMixin`, в котором реализовано хранение состояния точек (`state`, `changed`, `addr`).
|
|
27
|
+
|
|
28
|
+
### 🛠 Контроллер
|
|
29
|
+
Каждый контроллер реализует:
|
|
30
|
+
```python
|
|
31
|
+
self.interface = ControllerInterface(di_interface=..., relay_interface=...)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 🧪 Обёртки:
|
|
35
|
+
|
|
36
|
+
- `ControllerOperator` — отвечает за автоматическое обновление, mutex-безопасность и удобный API
|
|
37
|
+
- `ControllerCreator` — фабрика создания контроллеров по имени модели (см. `controller_factory.py`)
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## 🧪 Как использовать
|
|
42
|
+
|
|
43
|
+
```python
|
|
44
|
+
from gravity_controller_operator.controllers.moxa import MoxaE1214
|
|
45
|
+
from gravity_controller_operator.controller_operator import ControllerOperator
|
|
46
|
+
|
|
47
|
+
moxa = MoxaE1214("192.168.60.103")
|
|
48
|
+
operator = ControllerOperator(moxa)
|
|
49
|
+
|
|
50
|
+
print(operator.get_points())
|
|
51
|
+
operator.change_relay_state(0, 1) # включить реле 0
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 🔬 Тестирование
|
|
57
|
+
|
|
58
|
+
Установка:
|
|
59
|
+
```bash
|
|
60
|
+
pip install pytest
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Запуск:
|
|
64
|
+
```bash
|
|
65
|
+
pytest gravity_controller_operator/tests/
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 📦 Добавление нового контроллера
|
|
71
|
+
|
|
72
|
+
1. Реализуй `YourControllerDI` и `YourControllerRelay`, наследуя `DIInterface`, `RelayInterface`
|
|
73
|
+
2. Создай `YourController`, в котором:
|
|
74
|
+
```python
|
|
75
|
+
self.interface = ControllerInterface(di_interface=..., relay_interface=...)
|
|
76
|
+
```
|
|
77
|
+
3. Добавь контроллер в `AVAILABLE_CONTROLLERS` в `controller_factory.py`
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 📁 Структура
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
controllers_super.py # Базовые интерфейсы
|
|
85
|
+
controllers/ # Реализации контроллеров
|
|
86
|
+
controller_operator.py # Обёртка ControllerOperator ✅
|
|
87
|
+
controller_factory.py # AVAILABLE_CONTROLLERS + фабрика ✅
|
|
88
|
+
exceptions.py # Кастомные исключения ✅
|
|
89
|
+
tests/ # Тесты
|
|
90
|
+
README.md
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 🤝 Контакты
|
|
96
|
+
|
|
97
|
+
- 📧 Email: ksmdrmvstchny@gmail.com
|
|
98
|
+
- 💬 Telegram: [@PunchyArchy](https://t.me/PunchyArchy)
|
|
99
|
+
- 📞 Phone: +7 996 294-75-95
|
|
100
|
+
|
|
101
|
+
Проект поддерживается Артуром (PunchyArchy, Qodex)
|
|
File without changes
|
|
@@ -1,28 +1,29 @@
|
|
|
1
|
-
from gravity_controller_operator.controllers.emulator_contr import EmulatorController
|
|
2
|
-
from gravity_controller_operator.controllers.netping_relay import NetPing2Controller
|
|
3
|
-
from gravity_controller_operator.controllers.arm_k210 import ARMK210Controller
|
|
4
|
-
from gravity_controller_operator.controllers.wb_mr6lv import WBMR6LV
|
|
5
|
-
from gravity_controller_operator.exceptions import UnknownController
|
|
6
|
-
from gravity_controller_operator.controllers.moxa import MoxaE1214
|
|
7
|
-
from gravity_controller_operator.controllers.sigur import Sigur
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
AVAILABLE_CONTROLLERS = [
|
|
11
|
-
ARMK210Controller,
|
|
12
|
-
WBMR6LV,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
1
|
+
from gravity_controller_operator.controllers.emulator_contr import EmulatorController
|
|
2
|
+
from gravity_controller_operator.controllers.netping_relay import NetPing2Controller
|
|
3
|
+
from gravity_controller_operator.controllers.arm_k210 import ARMK210Controller
|
|
4
|
+
from gravity_controller_operator.controllers.wb_mr6lv import WBMR6LV, WBMR6LVTCP
|
|
5
|
+
from gravity_controller_operator.exceptions import UnknownController
|
|
6
|
+
from gravity_controller_operator.controllers.moxa import MoxaE1214
|
|
7
|
+
from gravity_controller_operator.controllers.sigur import Sigur
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
AVAILABLE_CONTROLLERS = [
|
|
11
|
+
ARMK210Controller,
|
|
12
|
+
WBMR6LV,
|
|
13
|
+
WBMR6LVTCP,
|
|
14
|
+
NetPing2Controller,
|
|
15
|
+
EmulatorController,
|
|
16
|
+
Sigur,
|
|
17
|
+
MoxaE1214
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ControllerCreator:
|
|
22
|
+
@staticmethod
|
|
23
|
+
def get_controller(model, emulator=False, *args, **kwargs):
|
|
24
|
+
for contr in AVAILABLE_CONTROLLERS:
|
|
25
|
+
if emulator:
|
|
26
|
+
return EmulatorController(*args, **kwargs)
|
|
27
|
+
if contr.model.lower() == model.lower():
|
|
28
|
+
return contr(*args, **kwargs)
|
|
29
|
+
raise UnknownController(model, [contr.model for contr in AVAILABLE_CONTROLLERS])
|
|
File without changes
|
|
@@ -1,47 +1,54 @@
|
|
|
1
|
-
from gravity_controller_operator.controllers_super import DIInterface, RelayInterface, ControllerInterface
|
|
2
|
-
from pyModbusTCP.client import ModbusClient
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class ARMK210ControllerDI(DIInterface):
|
|
6
|
-
map_keys_amount = 8
|
|
7
|
-
starts_with = 0
|
|
8
|
-
|
|
9
|
-
def __init__(self, client):
|
|
10
|
-
self.client = client
|
|
11
|
-
super().__init__()
|
|
12
|
-
|
|
13
|
-
def get_phys_dict(self):
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
response
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
1
|
+
from gravity_controller_operator.controllers_super import DIInterface, RelayInterface, ControllerInterface
|
|
2
|
+
from pyModbusTCP.client import ModbusClient
|
|
3
|
+
import time
|
|
4
|
+
|
|
5
|
+
class ARMK210ControllerDI(DIInterface):
|
|
6
|
+
map_keys_amount = 8
|
|
7
|
+
starts_with = 0
|
|
8
|
+
|
|
9
|
+
def __init__(self, client):
|
|
10
|
+
self.client = client
|
|
11
|
+
super().__init__()
|
|
12
|
+
|
|
13
|
+
def get_phys_dict(self):
|
|
14
|
+
for _ in range(5):
|
|
15
|
+
response = self.client.read_input_registers(self.starts_with, self.map_keys_amount)
|
|
16
|
+
if response:
|
|
17
|
+
return {i: val for i, val in enumerate(response)}
|
|
18
|
+
time.sleep(0.1) # Не грузим CPU и даём контроллеру время
|
|
19
|
+
return {"error": "No response from controller"}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ARMK210ControllerRelay(RelayInterface):
|
|
23
|
+
map_keys_amount = 8
|
|
24
|
+
starts_with = 0
|
|
25
|
+
|
|
26
|
+
def __init__(self, client):
|
|
27
|
+
self.client = client
|
|
28
|
+
super().__init__()
|
|
29
|
+
|
|
30
|
+
def get_phys_dict(self):
|
|
31
|
+
for _ in range(5):
|
|
32
|
+
response = self.client.read_holding_registers(self.starts_with, self.map_keys_amount)
|
|
33
|
+
if response:
|
|
34
|
+
return {i: val for i, val in enumerate(response)}
|
|
35
|
+
time.sleep(0.1) # Не грузим CPU и даём контроллеру время
|
|
36
|
+
return {"error": "No response from controller"}
|
|
37
|
+
|
|
38
|
+
def change_phys_relay_state(self, addr, state: bool):
|
|
39
|
+
for _ in range(5):
|
|
40
|
+
result = self.client.write_single_coil(addr, state)
|
|
41
|
+
if result:
|
|
42
|
+
return
|
|
43
|
+
time.sleep(0.1)
|
|
44
|
+
raise Exception("Failed to change relay state after 5 tries")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class ARMK210Controller:
|
|
48
|
+
model = "arm_k210"
|
|
49
|
+
|
|
50
|
+
def __init__(self, ip: str, port: int = 8234, name="ARM_K210_Controller", *args, **kwargs):
|
|
51
|
+
client = ModbusClient(host=ip, port=port)
|
|
52
|
+
di = ARMK210ControllerDI(client)
|
|
53
|
+
relay = ARMK210ControllerRelay(client)
|
|
54
|
+
self.interface = ControllerInterface(di_interface=di, relay_interface=relay)
|