pyaidrone 1.6__py3-none-any.whl → 1.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyaidrone might be problematic. Click here for more details.
- pyaidrone/aiDrone.py +65 -1
- pyaidrone/ikeyevent.py +8 -8
- {pyaidrone-1.6.dist-info → pyaidrone-1.7.dist-info}/METADATA +1 -1
- pyaidrone-1.7.dist-info/RECORD +10 -0
- pyaidrone-1.6.dist-info/RECORD +0 -10
- {pyaidrone-1.6.dist-info → pyaidrone-1.7.dist-info}/WHEEL +0 -0
- {pyaidrone-1.6.dist-info → pyaidrone-1.7.dist-info}/top_level.txt +0 -0
pyaidrone/aiDrone.py
CHANGED
|
@@ -22,7 +22,11 @@ class AIDrone(Parse, Packet):
|
|
|
22
22
|
self.posX = 0
|
|
23
23
|
self.posY = 0
|
|
24
24
|
self.rot = 0
|
|
25
|
-
|
|
25
|
+
# --- 영상 스트리밍 관련 기본값 ---
|
|
26
|
+
self.stream_host = "192.168.4.1"
|
|
27
|
+
self.stream_port = 80
|
|
28
|
+
self.stream_path = "/?action=stream"
|
|
29
|
+
self._cap = None
|
|
26
30
|
|
|
27
31
|
def receiveHandler(self):
|
|
28
32
|
while self.isThreadRun:
|
|
@@ -149,6 +153,66 @@ class AIDrone(Parse, Packet):
|
|
|
149
153
|
def emergency(self):
|
|
150
154
|
self.setOption(0x00)
|
|
151
155
|
self.serial.write(self.makepkt.getPacket())
|
|
156
|
+
|
|
157
|
+
# aiDrone.py — AIDrone 클래스 안에 아래 3개 메서드 추가
|
|
158
|
+
def setStreamAddress(self, host: str, port: int = 80, path: str = "/?action=stream"):
|
|
159
|
+
"""MJPG-Streamer 주소 구성 요소를 저장합니다."""
|
|
160
|
+
if not isinstance(host, str) or len(host.strip()) == 0:
|
|
161
|
+
raise ValueError("host가 올바르지 않습니다.")
|
|
162
|
+
self.stream_host = host.strip()
|
|
163
|
+
self.stream_port = int(port)
|
|
164
|
+
if not path.startswith("/"):
|
|
165
|
+
path = "/" + path
|
|
166
|
+
self.stream_path = path
|
|
167
|
+
return self._build_stream_url()
|
|
168
|
+
|
|
169
|
+
def _build_stream_url(self):
|
|
170
|
+
"""내부 사용: 저장된 host/port/path로 URL 생성."""
|
|
171
|
+
if self.stream_port in (80, None):
|
|
172
|
+
return f"http://{self.stream_host}{self.stream_path}"
|
|
173
|
+
return f"http://{self.stream_host}:{self.stream_port}{self.stream_path}"
|
|
174
|
+
|
|
175
|
+
def streamon(self, host: str = None, port: int = None, path: str = None, return_url: bool = False):
|
|
176
|
+
"""
|
|
177
|
+
MJPG-Streamer 스트림을 엽니다.
|
|
178
|
+
- 인자를 주면 해당 값으로 주소를 덮어쓰고, 안 주면 저장된 값 사용.
|
|
179
|
+
- return_url=True 이면 URL 문자열만 반환(캡처는 열지 않음).
|
|
180
|
+
- 기본 URL 예: http://192.168.4.1/?action=stream
|
|
181
|
+
"""
|
|
182
|
+
if host is not None or port is not None or path is not None:
|
|
183
|
+
self.setStreamAddress(host or self.stream_host,
|
|
184
|
+
self.stream_port if port is None else port,
|
|
185
|
+
self.stream_path if path is None else path)
|
|
186
|
+
|
|
187
|
+
url = self._build_stream_url()
|
|
188
|
+
if return_url:
|
|
189
|
+
return url
|
|
190
|
+
|
|
191
|
+
# OpenCV는 여기서만 임포트(필요할 때만)
|
|
192
|
+
try:
|
|
193
|
+
import cv2 as cv
|
|
194
|
+
except Exception as e:
|
|
195
|
+
raise RuntimeError(f"OpenCV(cv2) 임포트 실패: {e}")
|
|
196
|
+
|
|
197
|
+
# 이전 cap이 열려 있으면 정리
|
|
198
|
+
self.streamoff()
|
|
199
|
+
|
|
200
|
+
self._cap = cv.VideoCapture(url)
|
|
201
|
+
if not self._cap.isOpened():
|
|
202
|
+
self._cap.release()
|
|
203
|
+
self._cap = None
|
|
204
|
+
raise RuntimeError(f"스트림 열기 실패: {url}")
|
|
205
|
+
return self._cap
|
|
206
|
+
|
|
207
|
+
def streamoff(self):
|
|
208
|
+
"""열려 있는 스트림을 닫습니다."""
|
|
209
|
+
if self._cap is not None:
|
|
210
|
+
try:
|
|
211
|
+
self._cap.release()
|
|
212
|
+
except Exception:
|
|
213
|
+
pass
|
|
214
|
+
self._cap = None
|
|
215
|
+
|
|
152
216
|
|
|
153
217
|
|
|
154
218
|
|
pyaidrone/ikeyevent.py
CHANGED
|
@@ -22,8 +22,8 @@ class IKeyEvent:
|
|
|
22
22
|
self.keyLTurn = True
|
|
23
23
|
if key == keyboard.KeyCode(char="d"):
|
|
24
24
|
self.keyRTurn = True
|
|
25
|
-
if key == keyboard.KeyCode(char="
|
|
26
|
-
self.
|
|
25
|
+
if key == keyboard.KeyCode(char="s"):
|
|
26
|
+
self.keyPicture = True
|
|
27
27
|
if key == keyboard.Key.esc:
|
|
28
28
|
self.keyEsc = True
|
|
29
29
|
|
|
@@ -48,8 +48,8 @@ class IKeyEvent:
|
|
|
48
48
|
self.keyLTurn = False
|
|
49
49
|
if key == keyboard.KeyCode(char="d"):
|
|
50
50
|
self.keyRTurn = False
|
|
51
|
-
if key == keyboard.KeyCode(char="
|
|
52
|
-
self.
|
|
51
|
+
if key == keyboard.KeyCode(char="s"):
|
|
52
|
+
self.keyPicture = False
|
|
53
53
|
if key == keyboard.Key.esc:
|
|
54
54
|
self.keyEsc = False
|
|
55
55
|
|
|
@@ -58,13 +58,13 @@ class IKeyEvent:
|
|
|
58
58
|
self.keySpace = False
|
|
59
59
|
self.keyUp = False
|
|
60
60
|
self.keyDown = False
|
|
61
|
+
self.keyRight= False
|
|
61
62
|
self.keyLeft = False
|
|
62
|
-
self.keyRight = False
|
|
63
63
|
self.keyGoUp = False
|
|
64
64
|
self.keyGoDown = False
|
|
65
65
|
self.keyLTurn= False
|
|
66
66
|
self.keyRTurn = False
|
|
67
|
-
self.
|
|
67
|
+
self.keyPicture = False
|
|
68
68
|
self.keyEsc = False
|
|
69
69
|
|
|
70
70
|
listener = keyboard.Listener(on_press=self.on_press, on_release=self.on_release)
|
|
@@ -100,8 +100,8 @@ class IKeyEvent:
|
|
|
100
100
|
def isKeyDPressed(self):
|
|
101
101
|
return self.keyRTurn
|
|
102
102
|
|
|
103
|
-
def
|
|
104
|
-
return self.
|
|
103
|
+
def isKeySPressed(self):
|
|
104
|
+
return self.keyPicture
|
|
105
105
|
|
|
106
106
|
def isKeyEscPressed(self):
|
|
107
107
|
return self.keyEsc
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
pyaidrone/__init__.py,sha256=LTT-ZpL6vrKdC5t0O71pJnk3zMhDf1eXkNmoLoIRupo,19
|
|
2
|
+
pyaidrone/aiDrone.py,sha256=gGkD6MdcGmXDPxg02AGmpEO8uvqTusJ9g56HUctNWyY,7458
|
|
3
|
+
pyaidrone/deflib.py,sha256=ZeA_qfnhuXEIhJHUMNSKkCkBEaWuoIS5X7ZqjTo9Sx4,735
|
|
4
|
+
pyaidrone/ikeyevent.py,sha256=XSWCQjByvD5FswdOb2JSviaMlJO69IGnvbDWsDC1mG0,3140
|
|
5
|
+
pyaidrone/packet.py,sha256=h02k9dMUhP4oyEBaDuJ9L9HdutfZE_znreBmPOfTLog,813
|
|
6
|
+
pyaidrone/parse.py,sha256=XKfAVLo0nlciaxxFwui8CJIaB5B3ZGWF1L6zyfXICoA,1376
|
|
7
|
+
pyaidrone-1.7.dist-info/METADATA,sha256=3ztdm0ag7IUXBitcX9mReSXusryvinJzwKpsg_BANuw,593
|
|
8
|
+
pyaidrone-1.7.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
|
9
|
+
pyaidrone-1.7.dist-info/top_level.txt,sha256=YLnJwG3F2TdfFcg6r7jcx02fekcXHF_GC0nv12hJGT8,10
|
|
10
|
+
pyaidrone-1.7.dist-info/RECORD,,
|
pyaidrone-1.6.dist-info/RECORD
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
pyaidrone/__init__.py,sha256=LTT-ZpL6vrKdC5t0O71pJnk3zMhDf1eXkNmoLoIRupo,19
|
|
2
|
-
pyaidrone/aiDrone.py,sha256=3SU-4ratcze7XYORgb2Fhiw9g8s16AuCo5O7WkGmRmA,4776
|
|
3
|
-
pyaidrone/deflib.py,sha256=ZeA_qfnhuXEIhJHUMNSKkCkBEaWuoIS5X7ZqjTo9Sx4,735
|
|
4
|
-
pyaidrone/ikeyevent.py,sha256=5lqZFA_Wg4ntS8JF8bwHEJwPEoq1mEtR8Cwb8kJSivo,3124
|
|
5
|
-
pyaidrone/packet.py,sha256=h02k9dMUhP4oyEBaDuJ9L9HdutfZE_znreBmPOfTLog,813
|
|
6
|
-
pyaidrone/parse.py,sha256=XKfAVLo0nlciaxxFwui8CJIaB5B3ZGWF1L6zyfXICoA,1376
|
|
7
|
-
pyaidrone-1.6.dist-info/METADATA,sha256=2K2Ngl09jFASZK9fdxjrlYQq_uhz9uA25YLZC7daptg,593
|
|
8
|
-
pyaidrone-1.6.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
|
|
9
|
-
pyaidrone-1.6.dist-info/top_level.txt,sha256=YLnJwG3F2TdfFcg6r7jcx02fekcXHF_GC0nv12hJGT8,10
|
|
10
|
-
pyaidrone-1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|