mirror of
https://github.com/naruxde/revpicommander.git
synced 2025-11-09 00:53:53 +01:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c10a50fa56 | |||
| e4d18f7b4a | |||
| efd27cc96c | |||
| 0494ce53ad | |||
| c56c33f4e5 | |||
| e95bf70993 | |||
| 6ee53595e2 | |||
| a0b309ade0 | |||
| be03bbe6f3 | |||
| 92abe46152 | |||
| 27915e5a58 | |||
| a8e4638ab9 |
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -6,7 +6,7 @@
|
||||
<component name="ProjectPlainTextFileTypeManager">
|
||||
<file url="file://$PROJECT_DIR$/src/revpicommander/locale/revpicommander_de.ts" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (revpicommander)" project-jdk-type="Python SDK" />
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11 (revpicommander)" project-jdk-type="Python SDK" />
|
||||
<component name="PythonCompatibilityInspectionAdvertiser">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
|
||||
2
.idea/revpicommander.iml
generated
2
.idea/revpicommander.iml
generated
@@ -6,7 +6,7 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/build" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.9 (revpicommander)" jdkType="Python SDK" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.11 (revpicommander)" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="PackageRequirementsSettings">
|
||||
|
||||
2
.idea/vcs.xml
generated
2
.idea/vcs.xml
generated
@@ -3,6 +3,8 @@
|
||||
<component name="CommitMessageInspectionProfile">
|
||||
<profile version="1.0">
|
||||
<inspection_tool class="BodyLimit" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="CommitFormat" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="CommitNamingConvention" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SubjectBodySeparation" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="SubjectLimit" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
|
||||
52
Makefile
52
Makefile
@@ -8,61 +8,69 @@ APP_NAME = RevPi\ Commander
|
||||
APP_IDENT = org.revpimodio.revpicommander
|
||||
APPLE_SIG = "Developer ID Application: Sven Sager (U3N5843D9K)"
|
||||
|
||||
# If virtualenv exists, use it. If not, use PATH to find, except python3
|
||||
SYSTEM_PYTHON = /usr/bin/python3
|
||||
PYTHON = $(or $(wildcard venv/bin/python), $(SYSTEM_PYTHON))
|
||||
SYSTEM_PYUIC5 = $(shell which pyuic5)
|
||||
PYUIC5 = $(or $(wildcard venv/bin/pyuic5), $(SYSTEM_PYUIC5))
|
||||
SYSTEM_PYRCC5 = $(shell which pyrcc5)
|
||||
PYRCC5 = $(or $(wildcard venv/bin/pyrcc5), $(SYSTEM_PYRCC5))
|
||||
SYSTEM_PYLUP5 = $(shell which pylupdate5)
|
||||
PYLUP5 = $(or $(wildcard venv/bin/pylupdate5), $(SYSTEM_PYLUP5))
|
||||
# Set path to create the virtual environment with package name
|
||||
ifdef PYTHON3_VENV
|
||||
VENV_PATH = $(PYTHON3_VENV)/$(PACKAGE)
|
||||
else
|
||||
VENV_PATH = venv
|
||||
endif
|
||||
|
||||
# If virtualenv exists, use it. If not, use PATH to find commands
|
||||
SYSTEM_PYTHON = python3
|
||||
PYTHON = $(or $(wildcard $(VENV_PATH)/bin/python), $(SYSTEM_PYTHON))
|
||||
|
||||
APP_VERSION = $(shell $(PYTHON) src/$(PACKAGE) --version)
|
||||
|
||||
all: build_ui build_rc build
|
||||
all: build_ui build_rc test build
|
||||
|
||||
.PHONY: all
|
||||
|
||||
## Environment
|
||||
venv-info:
|
||||
echo Using path: "$(VENV_PATH)"
|
||||
exit 0
|
||||
|
||||
venv:
|
||||
$(SYSTEM_PYTHON) -m venv venv
|
||||
source venv/bin/activate && \
|
||||
$(SYSTEM_PYTHON) -m venv --system-site-packages "$(VENV_PATH)"
|
||||
source $(VENV_PATH)/bin/activate && \
|
||||
python3 -m pip install --upgrade pip && \
|
||||
python3 -m pip install -r requirements.txt
|
||||
exit 0
|
||||
|
||||
.PHONY: venv
|
||||
.PHONY: venv-info venv
|
||||
|
||||
## Compile Qt UI files to python code
|
||||
build_ui:
|
||||
cd ui_dev && for ui_file in *.ui; do \
|
||||
file_name=$${ui_file%.ui}; \
|
||||
$(PYUIC5) $${ui_file} -o ../src/$(PACKAGE)/ui/$${file_name}_ui.py -x --from-imports; \
|
||||
$(PYTHON) -m PyQt5.uic.pyuic $${ui_file} -o ../src/$(PACKAGE)/ui/$${file_name}_ui.py -x --from-imports; \
|
||||
echo $${file_name}; \
|
||||
done
|
||||
|
||||
build_rc:
|
||||
cd ui_dev && for rc_file in *.qrc; do \
|
||||
file_name=$${rc_file%.qrc}; \
|
||||
$(PYRCC5) $${rc_file} -o ../src/$(PACKAGE)/ui/$${file_name}_rc.py; \
|
||||
$(PYTHON) -m PyQt5.pyrcc_main $${rc_file} -o ../src/$(PACKAGE)/ui/$${file_name}_rc.py; \
|
||||
echo $${file_name}; \
|
||||
done
|
||||
|
||||
update_translation:
|
||||
$(PYLUP5) translate.pro
|
||||
$(PYTHON) -m PyQt5.pylupdate_main translate.pro
|
||||
|
||||
.PHONY: build_ui build_rc update_translation
|
||||
|
||||
## Build, install
|
||||
## Build steps
|
||||
build: build_ui build_rc
|
||||
$(PYTHON) -m setup sdist
|
||||
$(PYTHON) -m setup bdist_wheel
|
||||
|
||||
install: build
|
||||
install: test build
|
||||
$(PYTHON) -m pip install dist/$(PACKAGE)-*.whl
|
||||
|
||||
.PHONY: build install
|
||||
uninstall:
|
||||
$(PYTHON) -m pip uninstall --yes $(PACKAGE)
|
||||
|
||||
.PHONY: test build install uninstall
|
||||
|
||||
## PyInstaller
|
||||
installer_mac: build_ui build_rc
|
||||
@@ -114,7 +122,7 @@ installer_linux: build_ui build_rc
|
||||
clean:
|
||||
rm -rf build dist src/*.egg-info *.spec
|
||||
|
||||
clean-all: clean
|
||||
rm -R venv
|
||||
distclean: clean
|
||||
rm -rf $(VENV_PATH)
|
||||
|
||||
.PHONY: clean clean-all
|
||||
.PHONY: clean distclean
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#!/bin/sh
|
||||
# Used to call the entry point, if packed with pybuild as application.
|
||||
# PYBUILD_INSTALL_ARGS=--install-lib=/usr/share/revpicommander/ \
|
||||
# --install-scripts=/usr/share/revpicommander/
|
||||
#
|
||||
# In that case the entry point will not find the revpicommander module in
|
||||
# the python lib.
|
||||
# This script will create the entry point 'revpicommander', which is defined
|
||||
# in the setup.py script. If you want to install this python module as an
|
||||
# application and not in the python standard library directory, you will need
|
||||
# to use this script for /usr/bin.
|
||||
|
||||
exec "/usr/share/revpicommander/revpicommander-gui" "$@"
|
||||
exec python3 /usr/share/revpicommander/revpicommander "$@"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||
|
||||
#define MyAppName "RevPi Commander"
|
||||
#define MyAppVersion "0.9.10rc7"
|
||||
#define MyAppVersion "0.10.0"
|
||||
#define MyAppPublisher "Sven Sager"
|
||||
#define MyAppURL "https://revpimodio.org/"
|
||||
#define MyAppICO "data\revpicommander.ico"
|
||||
|
||||
2
setup.py
2
setup.py
@@ -25,7 +25,7 @@ setup(
|
||||
],
|
||||
entry_points={
|
||||
'gui_scripts': [
|
||||
'revpicommander-gui = revpicommander.revpicommander:main',
|
||||
'revpicommander = revpicommander.revpicommander:main',
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
@@ -4,4 +4,4 @@ __author__ = "Sven Sager"
|
||||
__copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||
__license__ = "GPLv2"
|
||||
__package__ = "revpicommander"
|
||||
__version__ = "0.9.10rc7"
|
||||
__version__ = "0.10.0"
|
||||
|
||||
@@ -38,9 +38,7 @@ class DebugIos(QtWidgets.QMainWindow, Ui_win_debugios):
|
||||
self.outputs = outputs.copy()
|
||||
self.write_values = False
|
||||
|
||||
min_input = min(inputs, key=lambda k: k[2])
|
||||
max_output = max(outputs, key=lambda k: k[2])
|
||||
self.length = max_output[2] + max_output[1] - min_input[2]
|
||||
self.length = self._calc_device_length(self.inputs, self.outputs)
|
||||
|
||||
self.style_sheet = ""
|
||||
self._create_io(self.inputs, self.saw_inp, True)
|
||||
@@ -62,6 +60,23 @@ class DebugIos(QtWidgets.QMainWindow, Ui_win_debugios):
|
||||
return max_int_value / 2 * -1 if signed else 0.0, \
|
||||
max_int_value / 2 - 1 if signed else max_int_value - 1
|
||||
|
||||
@staticmethod
|
||||
def _calc_device_length(inputs: list, outputs: list) -> int:
|
||||
"""Calculate the device length with IO data."""
|
||||
if inputs and outputs:
|
||||
min_input = min(inputs, key=lambda k: k[2])
|
||||
max_output = max(outputs, key=lambda k: k[2])
|
||||
elif inputs:
|
||||
min_input = min(inputs, key=lambda k: k[2])
|
||||
max_output = max(inputs, key=lambda k: k[2])
|
||||
elif outputs:
|
||||
min_input = min(outputs, key=lambda k: k[2])
|
||||
max_output = max(outputs, key=lambda k: k[2])
|
||||
else:
|
||||
return 0
|
||||
|
||||
return max_output[2] + max_output[1] - min_input[2]
|
||||
|
||||
def _create_io(self, lst_ios: list, container: QtWidgets.QWidget, read_only: bool):
|
||||
lst_names = list(lst[0] for lst in lst_ios)
|
||||
layout = container.layout() # type: QtWidgets.QFormLayout
|
||||
@@ -293,10 +308,7 @@ class DebugIos(QtWidgets.QMainWindow, Ui_win_debugios):
|
||||
"""Update IOs after driver reset of piCtory."""
|
||||
|
||||
# Check device length, this has to match to reuse this device
|
||||
min_input = min(inputs, key=lambda k: k[2])
|
||||
max_output = max(outputs, key=lambda k: k[2])
|
||||
new_length = max_output[2] + max_output[1] - min_input[2]
|
||||
if self.length != new_length:
|
||||
if self.length != self._calc_device_length(inputs, outputs):
|
||||
return False
|
||||
|
||||
# Remove IOs, which was remove or renamed
|
||||
|
||||
@@ -33,6 +33,7 @@ class ConnectionFail(IntEnum):
|
||||
NO_XML_RPC = 1
|
||||
SSH_CONNECT = 2
|
||||
SSH_AUTH = 4
|
||||
NO_XML_RPC_VIA_TUNNEL = 9 # Includes NO_XML_RPC Bit
|
||||
|
||||
|
||||
class WidgetData(IntEnum):
|
||||
@@ -347,6 +348,10 @@ class ConnectionManager(QtCore.QThread):
|
||||
)
|
||||
try:
|
||||
ssh_tunnel_port = ssh_tunnel_server.connect_by_credentials(revpi_settings.ssh_user, ssh_pass)
|
||||
|
||||
if getattr(revpi_settings, "ssh_enable_revpipyload", False):
|
||||
ssh_tunnel_server.send_cmd("sudo systemctl enable --now revpipyload")
|
||||
|
||||
except AuthenticationException:
|
||||
self.connect_error.emit(
|
||||
self.tr("Error"), self.tr(
|
||||
@@ -394,7 +399,7 @@ class ConnectionManager(QtCore.QThread):
|
||||
"- The RevPiPyLoad XML-RPC service is NOT bind to localhost\n"
|
||||
"- The ACL permission is not set for 127.0.0.1!!!"
|
||||
),
|
||||
ConnectionFail.NO_XML_RPC,
|
||||
ConnectionFail.NO_XML_RPC_VIA_TUNNEL,
|
||||
revpi_settings,
|
||||
)
|
||||
else:
|
||||
@@ -471,7 +476,13 @@ class ConnectionManager(QtCore.QThread):
|
||||
self.connection_disconnected.emit()
|
||||
|
||||
def pyload_simulate(self, configrsc: str, procimg: str, clean_existing: bool):
|
||||
"""Start the simulator for piControl on local computer."""
|
||||
"""
|
||||
Start the simulator for piControl on local computer.
|
||||
|
||||
:param configrsc: piCtory configuration
|
||||
:param procimg: Process image, which is a 4 kByte file for simulation
|
||||
:param clean_existing: Reset the file to ZERO \x00 bytes
|
||||
"""
|
||||
pi.logger.debug("ConnectionManager.start_simulate")
|
||||
|
||||
if not exists(procimg) or clean_existing:
|
||||
|
||||
Binary file not shown.
@@ -229,62 +229,62 @@ Wurde eine Hardwarekonfiguration in piCtory erzeugt?</translation>
|
||||
<context>
|
||||
<name>ConnectionManager</name>
|
||||
<message>
|
||||
<location filename="../helper.py" line="533"/>
|
||||
<location filename="../helper.py" line="538"/>
|
||||
<source>SIMULATING</source>
|
||||
<translation>SIMULATION</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="536"/>
|
||||
<location filename="../helper.py" line="541"/>
|
||||
<source>NOT CONNECTED</source>
|
||||
<translation>NICHT VERBUNDEN</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="553"/>
|
||||
<location filename="../helper.py" line="558"/>
|
||||
<source>SERVER ERROR</source>
|
||||
<translation>SERVER FEHLER</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="578"/>
|
||||
<location filename="../helper.py" line="583"/>
|
||||
<source>RUNNING</source>
|
||||
<translation>LÄUFT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="580"/>
|
||||
<location filename="../helper.py" line="585"/>
|
||||
<source>PLC FILE NOT FOUND</source>
|
||||
<translation>SPS PROGRAMM NICHT GEFUNDEN</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="582"/>
|
||||
<location filename="../helper.py" line="587"/>
|
||||
<source>NOT RUNNING (NO STATUS)</source>
|
||||
<translation>LÄUFT NICHT (KEIN STATUS)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="584"/>
|
||||
<location filename="../helper.py" line="589"/>
|
||||
<source>PROGRAM KILLED</source>
|
||||
<translation>PROGRAMM GETÖTET</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="586"/>
|
||||
<location filename="../helper.py" line="591"/>
|
||||
<source>PROGRAM TERMED</source>
|
||||
<translation>PROGRAMM BEENDET</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="588"/>
|
||||
<location filename="../helper.py" line="593"/>
|
||||
<source>NOT RUNNING</source>
|
||||
<translation>LÄUFT NICHT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="590"/>
|
||||
<location filename="../helper.py" line="595"/>
|
||||
<source>FINISHED WITH CODE {0}</source>
|
||||
<translation>BEENDET MIT CODE {0}</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="401"/>
|
||||
<location filename="../helper.py" line="406"/>
|
||||
<source>Error</source>
|
||||
<translation>Fehler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="351"/>
|
||||
<location filename="../helper.py" line="356"/>
|
||||
<source>The combination of username and password was rejected from the SSH server.
|
||||
|
||||
Try again.</source>
|
||||
@@ -293,7 +293,7 @@ Try again.</source>
|
||||
Bitte erneut versuchen.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="363"/>
|
||||
<location filename="../helper.py" line="368"/>
|
||||
<source>Could not establish a SSH connection to server:
|
||||
|
||||
{0}</source>
|
||||
@@ -352,7 +352,7 @@ Das kann eine der folgenden Ursachen haben:
|
||||
Benutze "Über SSH verbinden" um eine verschlüsselte Verbindung aufzubauen oder führe 'sudo revpipyload_secure_installation' auf dem Revolution Pi aus, um eine direkte Verbindung zu konfigurieren!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="401"/>
|
||||
<location filename="../helper.py" line="406"/>
|
||||
<source>Can not connect to RevPiPyLoad XML-RPC service!
|
||||
|
||||
This could have the following reasons:
|
||||
@@ -373,7 +373,7 @@ Das kann eine der folgenden Ursachen haben:
|
||||
Benutze "Über SSH verbinden" um eine verschlüsselte Verbindung aufzubauen oder führe 'sudo revpipyload_secure_installation' auf dem Revolution Pi aus, um eine direkte Verbindung zu konfigurieren!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../helper.py" line="389"/>
|
||||
<location filename="../helper.py" line="394"/>
|
||||
<source>Can not connect to RevPiPyLoad service through SSH tunnel!
|
||||
|
||||
This could have the following reasons:
|
||||
@@ -426,37 +426,37 @@ Das kann eine der folgenden Ursachen haben:
|
||||
<context>
|
||||
<name>DebugIos</name>
|
||||
<message>
|
||||
<location filename="../debugios.py" line="213"/>
|
||||
<location filename="../debugios.py" line="228"/>
|
||||
<source>signed</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugios.py" line="218"/>
|
||||
<location filename="../debugios.py" line="233"/>
|
||||
<source>big_endian</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugios.py" line="204"/>
|
||||
<location filename="../debugios.py" line="219"/>
|
||||
<source>as text</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugios.py" line="206"/>
|
||||
<location filename="../debugios.py" line="221"/>
|
||||
<source>as number</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugios.py" line="365"/>
|
||||
<location filename="../debugios.py" line="377"/>
|
||||
<source>Can not use format text</source>
|
||||
<translation>Formatierung nicht möglich</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugios.py" line="365"/>
|
||||
<location filename="../debugios.py" line="377"/>
|
||||
<source>Can not convert bytes {0} to a text for IO '{1}'. Switch to number format instead!</source>
|
||||
<translation>Kann bytes {0} für '{1}' nicht in Text konvertieren. Wechseln Sie auf Nummernformat!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../debugios.py" line="224"/>
|
||||
<location filename="../debugios.py" line="239"/>
|
||||
<source>switch wordorder</source>
|
||||
<translation>Wordorder tauschen</translation>
|
||||
</message>
|
||||
@@ -489,86 +489,86 @@ Ungesicherte Änderungen gehen verloren.</translation>
|
||||
<context>
|
||||
<name>RevPiCommander</name>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="308"/>
|
||||
<location filename="../revpicommander.py" line="320"/>
|
||||
<source>Simulator started...</source>
|
||||
<translation>Simulator gestartet...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="317"/>
|
||||
<location filename="../revpicommander.py" line="329"/>
|
||||
<source>Can not start...</source>
|
||||
<translation>Kann nicht gestartet werden...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="510"/>
|
||||
<location filename="../revpicommander.py" line="522"/>
|
||||
<source>Warning</source>
|
||||
<translation>Warnung</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="333"/>
|
||||
<location filename="../revpicommander.py" line="345"/>
|
||||
<source>This version of Logviewer ist not supported in version {0} of RevPiPyLoad on your RevPi! You need at least version 0.4.1.</source>
|
||||
<translation>Diese Version vom Logbetrachter wird in RevPiPyLoad Version {0} nicht unterstützt! Es wird mindestens Version 0.4.1 benötigt.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="383"/>
|
||||
<location filename="../revpicommander.py" line="395"/>
|
||||
<source>XML-RPC access mode in the RevPiPyLoad configuration is too small to access this dialog!</source>
|
||||
<translation>XML-RPC Zugriffsberechtigung in der RevPiPyLoad Konfiguraiton ist zu klein für diese Einstellungen!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="537"/>
|
||||
<location filename="../revpicommander.py" line="549"/>
|
||||
<source>Error</source>
|
||||
<translation>Fehler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="363"/>
|
||||
<location filename="../revpicommander.py" line="375"/>
|
||||
<source>The Version of RevPiPyLoad on your Revolution Pi ({0}) is to old. This Version of RevPiCommander require at least version 0.6.0 of RevPiPyLoad. Please update your Revolution Pi!</source>
|
||||
<translation>Die Version von RevPiPyLoad ({0}) auf dem Revolution Pi ist zu alt. Diese Version vom RevPiCommander braucht mindestens Version 0.6.0. Bitte aktualisiere deinen Revolution Pi!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="416"/>
|
||||
<location filename="../revpicommander.py" line="428"/>
|
||||
<source>Question</source>
|
||||
<translation>Frage</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="416"/>
|
||||
<location filename="../revpicommander.py" line="428"/>
|
||||
<source>Are you sure to reset piControl?
|
||||
The pictory configuration will be reloaded. During that time the process image will be interrupted and could rise errors on running control programs!</source>
|
||||
<translation>Soll piControl wirklich zurückgesetzt werden?
|
||||
Die piCtory Konfiguration wird neu geladen. Das Prozessabbild wird in dieser Zeit nicht verfügbar sein und es könnten Fehler in Steuerungsprogrammen ausgelöst werden!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="429"/>
|
||||
<location filename="../revpicommander.py" line="441"/>
|
||||
<source>Success</source>
|
||||
<translation>Erfolgreich</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="429"/>
|
||||
<location filename="../revpicommander.py" line="441"/>
|
||||
<source>piControl reset executed successfully</source>
|
||||
<translation>piControl wurde erfolgreich zurückgesetzt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="436"/>
|
||||
<location filename="../revpicommander.py" line="448"/>
|
||||
<source>piControl reset could not be executed successfully</source>
|
||||
<translation>piControl konnte nicht zurückgesetzt werden</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="484"/>
|
||||
<location filename="../revpicommander.py" line="496"/>
|
||||
<source>Reset to piCtory defaults...</source>
|
||||
<translation>Standardwerte von piCtory laden...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="510"/>
|
||||
<location filename="../revpicommander.py" line="522"/>
|
||||
<source>The watch mode ist not supported in version {0} of RevPiPyLoad on your RevPi! You need at least version 0.5.3! Maybe the python3-revpimodio2 module is not installed on your RevPi at least version 2.0.0.</source>
|
||||
<translation>Der SPS Betrachter ist in Version {0} von RevPiPyLoad auf dem Rev Pi nicht unterstützt! Es muss mindestens Version 0.5.3 installiert sein! Vielleicht fehlt auch das python3-revpimodio2 Modul, welches mindestens Version 2.0.0 haben muss.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="522"/>
|
||||
<location filename="../revpicommander.py" line="534"/>
|
||||
<source>Can not load this function, because your ACL level is to low!
|
||||
You need at least level 1 to read or level 3 to write.</source>
|
||||
<translation>Für diese Funktion ist das Berechtigungslevel zu gering!
|
||||
Es muss mindestens Level 1 zum Lesen oder Level 3 zu Schreiben sein.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="537"/>
|
||||
<location filename="../revpicommander.py" line="549"/>
|
||||
<source>Can not load piCtory configuration.
|
||||
Did you create a hardware configuration? Please check this in piCtory!</source>
|
||||
<translation>Kann piCtory Konfiguration nicht laden.
|
||||
@@ -588,7 +588,7 @@ Das kann eine der folgenden Ursachen haben: Der Rev Pi ist nicht online, der XML
|
||||
Führe 'sudo revpipyload_secure_installation' auf dem Revolution Pi aus um diese Funktion zu konfigurieren!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="308"/>
|
||||
<location filename="../revpicommander.py" line="320"/>
|
||||
<source>The simulator is running!
|
||||
|
||||
You can work with this simulator if your call RevPiModIO with this additional parameters:
|
||||
@@ -605,42 +605,65 @@ configrsc={1}
|
||||
Dies kann aus der Textbox oben kopiert werden.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="317"/>
|
||||
<location filename="../revpicommander.py" line="329"/>
|
||||
<source>Can not start the simulator! Maybe the piCtory file is corrupt or you have no write permissions for '{0}'.</source>
|
||||
<translation>Kann Simulator nicht starten! Vielleicht ist die piCtory Datei defekt oder es gibt keine Schreibberechtigung für '{0}'.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="484"/>
|
||||
<location filename="../revpicommander.py" line="496"/>
|
||||
<source>Do you want to reset your process image to {0} values?
|
||||
You have to stop other RevPiModIO programs before doing that, because they could reset the outputs.</source>
|
||||
<translation>Soll das virtuelle Prozessabbild auf {0} zurückgesetzt werden?
|
||||
Es sollten alle RevPiModIO Programme vorher beendet werden, da diese ihre IO Werte sofort wieder schreiben würden.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="484"/>
|
||||
<location filename="../revpicommander.py" line="496"/>
|
||||
<source>zero</source>
|
||||
<translation>null</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="484"/>
|
||||
<location filename="../revpicommander.py" line="496"/>
|
||||
<source>piCtory default</source>
|
||||
<translation>piCtory Standardwerte</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="238"/>
|
||||
<location filename="../revpicommander.py" line="250"/>
|
||||
<source>Revolution Pi connected!</source>
|
||||
<translation>Revolution Pi verbunden!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="275"/>
|
||||
<location filename="../revpicommander.py" line="287"/>
|
||||
<source>Connecting...</source>
|
||||
<translation>Verbinde...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="238"/>
|
||||
<location filename="../revpicommander.py" line="250"/>
|
||||
<source>Establish a connection to the Revolution Pi...</source>
|
||||
<translation>Baue eine Verbindung zum Revolution Pi auf...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="133"/>
|
||||
<source>Can not connect to RevPiPyLoad service through SSH tunnel!
|
||||
|
||||
We are trying to activate this service now and reconnect. The settings can be changed at any time via web status.</source>
|
||||
<translation type="obsolete">Über den SSH Tunnel kann keine Verbindung zu RevPiPyLoad hergestellt werden!
|
||||
|
||||
Wir werden versuchen den Dienst zu starten und eine neue Verbindung herzustellen. Diese Einstellung kann im Webstatus geändert werden.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="133"/>
|
||||
<source>Information</source>
|
||||
<translation>Information</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../revpicommander.py" line="133"/>
|
||||
<source>Can not connect to RevPiPyLoad service through SSH tunnel!
|
||||
|
||||
We are trying to activate this service now and reconnect. The settings can be changed at any time via 'webstatus'.</source>
|
||||
<translation>Vielleicht läuft der RevPiPyLoad Dienst nicht.
|
||||
|
||||
Wir versuchen diesen Dienst jetzt zu aktivieren und verbinden uns neu. Die Einstellungen können über 'Webstatus' jederzeit geändert werden.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>RevPiFiles</name>
|
||||
@@ -1216,12 +1239,12 @@ Dies ist kein Fehler von RevPi Commander.</translation>
|
||||
<context>
|
||||
<name>Simulator</name>
|
||||
<message>
|
||||
<location filename="../simulator.py" line="79"/>
|
||||
<location filename="../simulator.py" line="80"/>
|
||||
<source>Select downloaded piCtory file...</source>
|
||||
<translation>Heruntergeladene piCtory Datei auswählen...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../simulator.py" line="79"/>
|
||||
<location filename="../simulator.py" line="80"/>
|
||||
<source>piCtory file (*.rsc);;All files (*.*)</source>
|
||||
<translation>piCtory Datei (*.rsc);;Alle Dateien (*.*)</translation>
|
||||
</message>
|
||||
|
||||
@@ -128,10 +128,22 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
|
||||
:param fail_code: Type of error
|
||||
:param revpi_settings: Settings of the revpi with the error
|
||||
"""
|
||||
QtWidgets.QMessageBox.critical(self, title, text)
|
||||
if fail_code is ConnectionFail.SSH_AUTH:
|
||||
# On failed credentials, we try to connect again and remove password form keychain, if exists
|
||||
self._pyload_connect(revpi_settings, True)
|
||||
if fail_code is ConnectionFail.NO_XML_RPC_VIA_TUNNEL:
|
||||
# If RevPiPyLoad is not running, we can try to activate it via ssh
|
||||
QtWidgets.QMessageBox.information(
|
||||
self, self.tr("Information"), self.tr(
|
||||
"Can not connect to RevPiPyLoad service through SSH tunnel!\n\n"
|
||||
"We are trying to activate this service now and reconnect. The settings can be "
|
||||
"changed at any time via 'webstatus'."
|
||||
),
|
||||
)
|
||||
revpi_settings.ssh_enable_revpipyload = True
|
||||
self._pyload_connect(revpi_settings, False)
|
||||
else:
|
||||
QtWidgets.QMessageBox.critical(self, title, text)
|
||||
if fail_code is ConnectionFail.SSH_AUTH:
|
||||
# On failed credentials, we try to connect again and remove password form keychain, if exists
|
||||
self._pyload_connect(revpi_settings, True)
|
||||
|
||||
@QtCore.pyqtSlot(str)
|
||||
def on_cm_connection_error_observed(self, message: str):
|
||||
@@ -304,7 +316,7 @@ class RevPiCommander(QtWidgets.QMainWindow, Ui_win_revpicommander):
|
||||
configrsc_file = helper.settings.value("simulator/configrsc", "", str)
|
||||
procimg_file = helper.settings.value("simulator/procimg", "", str)
|
||||
|
||||
if helper.cm.pyload_simulate(configrsc_file, procimg_file, diag.cbx_stop_remove.isChecked()):
|
||||
if helper.cm.pyload_simulate(configrsc_file, procimg_file, diag.clean_procimg):
|
||||
QtWidgets.QMessageBox.information(
|
||||
self, self.tr("Simulator started..."), self.tr(
|
||||
"The simulator is running!\n\nYou can work with this simulator if your call "
|
||||
|
||||
@@ -167,8 +167,8 @@ class RevPiProgram(QtWidgets.QDialog, Ui_diag_program):
|
||||
return QtWidgets.QDialog.Rejected
|
||||
|
||||
self.dc = helper.cm.call_remote_function("get_config", default_value={})
|
||||
self.lst_files = helper.cm.call_remote_function("get_filelist", default_value=[])
|
||||
if len(self.dc) == 0 or len(self.lst_files) == 0:
|
||||
self.lst_files = helper.cm.call_remote_function("get_filelist", default_value=None)
|
||||
if len(self.dc) == 0 or self.lst_files is None:
|
||||
return QtWidgets.QDialog.Rejected
|
||||
|
||||
self._load_settings()
|
||||
|
||||
@@ -10,14 +10,18 @@ __copyright__ = "Copyright (C) 2023 Sven Sager"
|
||||
__license__ = "GPLv2"
|
||||
|
||||
import select
|
||||
from logging import getLogger
|
||||
from socketserver import BaseRequestHandler, ThreadingTCPServer
|
||||
from threading import Thread
|
||||
from typing import Tuple, Union
|
||||
|
||||
from paramiko.client import MissingHostKeyPolicy, SSHClient
|
||||
from paramiko.rsakey import RSAKey
|
||||
from paramiko.ssh_exception import PasswordRequiredException
|
||||
from paramiko.transport import Transport
|
||||
|
||||
log = getLogger("ssh_tunneling")
|
||||
|
||||
|
||||
class ForwardServer(ThreadingTCPServer):
|
||||
daemon_threads = True
|
||||
@@ -33,10 +37,14 @@ class Handler(BaseRequestHandler):
|
||||
self.request.getpeername(),
|
||||
)
|
||||
except Exception as e:
|
||||
log.error(e)
|
||||
return
|
||||
if chan is None:
|
||||
log.error("Could not create a ssh channel")
|
||||
return
|
||||
|
||||
log.info("Starting tunnel exchange loop")
|
||||
|
||||
while True:
|
||||
r, w, x = select.select([self.request, chan], [], [], 5.0)
|
||||
if self.request in r:
|
||||
@@ -50,6 +58,8 @@ class Handler(BaseRequestHandler):
|
||||
break
|
||||
self.request.send(data)
|
||||
|
||||
log.info("Stopped tunnel exchange loop")
|
||||
|
||||
chan.close()
|
||||
self.request.close()
|
||||
|
||||
@@ -162,6 +172,30 @@ class SSHLocalTunnel:
|
||||
return True
|
||||
return False
|
||||
|
||||
def send_cmd(self, cmd: str, timeout: float = None) -> Union[Tuple[str, str], Tuple[None, None]]:
|
||||
"""
|
||||
Send simple command to ssh host.
|
||||
|
||||
The output of stdout and stderr is returned as a tuple of two elements.
|
||||
This elements could be None, in case of an internal error.
|
||||
|
||||
:param cmd: Shell command to execute on remote host
|
||||
:param timeout: Timeout for execution
|
||||
:return: Tuple with stdout and stderr
|
||||
"""
|
||||
if not self._th_server.is_alive():
|
||||
raise RuntimeError("Not connected")
|
||||
|
||||
try:
|
||||
_, stdout, stderr = self._ssh_client.exec_command(cmd, 1024, timeout)
|
||||
buffer_out = stdout.read()
|
||||
buffer_err = stderr.read()
|
||||
|
||||
return buffer_out.decode(), buffer_err.decode()
|
||||
except Exception as e:
|
||||
log.error(e)
|
||||
return None, None
|
||||
|
||||
@property
|
||||
def connected(self):
|
||||
"""Check connection state of ssh tunnel."""
|
||||
|
||||
Reference in New Issue
Block a user