Skip to content

Commit 27a12ad

Browse files
committed
Added username and password for RTSP
1 parent 71cf502 commit 27a12ad

File tree

4 files changed

+95
-18
lines changed

4 files changed

+95
-18
lines changed

examples/official/ip_camera/gui_client/barcode_scanner.py

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,35 @@
44
Integrates Dynamsoft Capture Vision Bundle for real-time barcode detection.
55
"""
66

7+
import os
8+
import sys
79
import queue
810
import threading
911
import time
1012
from typing import List, Optional
1113
from PySide6.QtCore import QObject, Signal, QTimer
1214

15+
# Add Dynamsoft library path to DLL search path (for PyInstaller packaging)
16+
def _add_dynamsoft_to_dll_path():
17+
"""Add dynamsoft library directory to DLL search path"""
18+
if hasattr(sys, '_MEIPASS'):
19+
# Temporary directory after PyInstaller packaging
20+
dcvb_path = os.path.join(sys._MEIPASS, 'dynamsoft_capture_vision_bundle')
21+
if os.path.exists(dcvb_path):
22+
# Windows: Add DLL search path
23+
try:
24+
os.add_dll_directory(dcvb_path)
25+
# Also add to PATH environment variable (some DLLs may need this)
26+
os.environ['PATH'] = dcvb_path + os.pathsep + os.environ.get('PATH', '')
27+
except Exception as e:
28+
print(f"Warning: Failed to add DLL directory: {e}")
29+
30+
# Call before importing Dynamsoft
31+
_add_dynamsoft_to_dll_path()
32+
1333
from dynamsoft_capture_vision_bundle import (
14-
LicenseManager, CaptureVisionRouter, ImageSourceAdapter,
15-
CapturedResultReceiver, EnumErrorCode, EnumPresetTemplate,
34+
LicenseManager, CaptureVisionRouter, ImageSourceAdapter,
35+
CapturedResultReceiver, EnumErrorCode, EnumPresetTemplate,
1636
EnumCapturedResultItemType
1737
)
1838
from utils import convertMat2ImageData
@@ -84,23 +104,49 @@ def __init__(self, parent=None):
84104
# Initialize license
85105
self._initialize_license()
86106

87-
def _initialize_license(self):
107+
def _initialize_license(self, license_key=None):
88108
"""Initialize Dynamsoft license"""
89109
try:
90-
license_key = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="
110+
# Use provided key or load from config
111+
if not license_key:
112+
license_key = self._load_license_from_config()
91113

114+
if not license_key:
115+
self.error_occurred.emit("No license key found. Please configure it in config.json")
116+
return
117+
92118
error_code, error_msg = LicenseManager.init_license(license_key)
93-
119+
94120
if error_code != EnumErrorCode.EC_OK and error_code != EnumErrorCode.EC_LICENSE_CACHE_USED:
95121
self.error_occurred.emit(f"License initialization failed: {error_msg}")
96122
return
97-
123+
98124
self.is_initialized = True
99125
self._setup_scanner()
100-
126+
101127
except Exception as e:
102128
self.error_occurred.emit(f"Failed to initialize barcode scanner: {str(e)}")
103129

130+
def _load_license_from_config(self):
131+
"""Load license key from config.json"""
132+
import os
133+
import json
134+
135+
try:
136+
config_path = os.path.join(os.path.dirname(__file__), 'config.json')
137+
if os.path.exists(config_path):
138+
with open(config_path, 'r') as f:
139+
config = json.load(f)
140+
# Check multiple possible keys for compatibility
141+
license_key = (config.get('dynamsoft_license') or
142+
config.get('license_key') or
143+
config.get('barcode', {}).get('license_key'))
144+
return license_key
145+
except Exception as e:
146+
print(f"Error loading license from config: {e}")
147+
148+
return None
149+
104150
def _setup_scanner(self):
105151
"""Setup Dynamsoft Capture Vision components"""
106152
try:

examples/official/ip_camera/gui_client/config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,6 @@
3535
"start_fullscreen": false,
3636
"theme": 0,
3737
"user_agent": "IP-Camera-GUI-Client/1.0",
38-
"video_fit_mode": 0
38+
"video_fit_mode": 0,
39+
"dynamsoft_license": "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="
3940
}

examples/official/ip_camera/gui_client/dialogs.py

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def __init__(self, parent=None):
5252
super().__init__(parent)
5353
self.setWindowTitle("Connect to IP Camera")
5454
self.setModal(True)
55-
self.resize(400, 250)
55+
self.resize(420, 320)
5656

5757
self.setup_ui()
5858

@@ -122,7 +122,21 @@ def setup_quick_connect_form(self, layout):
122122
self.path_edit.setText("/video_feed")
123123
self.path_edit.textChanged.connect(self.update_url_preview)
124124
form_layout.addRow("Stream Path:", self.path_edit)
125-
125+
126+
# RTSP credentials (username / password)
127+
self.rtsp_username_label = QLabel("Username (RTSP):")
128+
self.rtsp_username_edit = QLineEdit()
129+
self.rtsp_username_edit.setPlaceholderText("Leave blank if not required")
130+
self.rtsp_username_edit.textChanged.connect(self.update_url_preview)
131+
form_layout.addRow(self.rtsp_username_label, self.rtsp_username_edit)
132+
133+
self.rtsp_password_label = QLabel("Password (RTSP):")
134+
self.rtsp_password_edit = QLineEdit()
135+
self.rtsp_password_edit.setPlaceholderText("Leave blank if not required")
136+
self.rtsp_password_edit.setEchoMode(QLineEdit.Password)
137+
self.rtsp_password_edit.textChanged.connect(self.update_url_preview)
138+
form_layout.addRow(self.rtsp_password_label, self.rtsp_password_edit)
139+
126140
# URL preview
127141
self.url_preview = QLabel()
128142
self.url_preview.setStyleSheet("""
@@ -138,21 +152,27 @@ def setup_quick_connect_form(self, layout):
138152

139153
layout.addLayout(form_layout)
140154

141-
# Update preview initially
155+
# Update preview initially (also sets visibility of credential fields)
142156
self.on_protocol_changed()
143157
self.update_url_preview()
144158

145159
def on_protocol_changed(self):
146160
"""Handle protocol change"""
147161
is_rtsp = "RTSP" in self.stream_protocol_combo.currentText()
148-
162+
149163
if is_rtsp:
150164
self.port_spinbox.setValue(554) # Default RTSP port
151165
self.path_edit.setText("/stream")
152166
else:
153167
self.port_spinbox.setValue(5000) # Default HTTP port
154168
self.path_edit.setText("/video_feed")
155-
169+
170+
# Show/hide credential fields based on protocol
171+
self.rtsp_username_label.setVisible(is_rtsp)
172+
self.rtsp_username_edit.setVisible(is_rtsp)
173+
self.rtsp_password_label.setVisible(is_rtsp)
174+
self.rtsp_password_edit.setVisible(is_rtsp)
175+
156176
self.update_url_preview()
157177

158178

@@ -161,17 +181,26 @@ def update_url_preview(self):
161181
ip = self.ip_edit.text() or "0.0.0.0"
162182
port = self.port_spinbox.value()
163183
path = self.path_edit.text() or "/"
164-
184+
165185
if not path.startswith('/'):
166186
path = '/' + path
167-
187+
168188
is_rtsp = "RTSP" in self.stream_protocol_combo.currentText()
169-
189+
170190
if is_rtsp:
171-
url = f"rtsp://{ip}:{port}{path}"
191+
username = self.rtsp_username_edit.text().strip()
192+
password = self.rtsp_password_edit.text()
193+
if username:
194+
# Embed credentials in the URL: rtsp://user:pass@host:port/path
195+
from urllib.parse import quote
196+
encoded_user = quote(username, safe='')
197+
encoded_pass = quote(password, safe='')
198+
url = f"rtsp://{encoded_user}:{encoded_pass}@{ip}:{port}{path}"
199+
else:
200+
url = f"rtsp://{ip}:{port}{path}"
172201
else:
173202
url = f"http://{ip}:{port}{path}"
174-
203+
175204
self.url_preview.setText(url)
176205

177206
def get_current_url(self):

examples/official/ip_camera/gui_client/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ requests==2.31.0
33
opencv-python==4.8.1.78
44
numpy>=1.21.0,<2.0.0
55
dynamsoft-capture-vision-bundle>=3.0.6000
6+
pyinstaller>=6.0.0

0 commit comments

Comments
 (0)