Compare commits
No commits in common. "ecac90373c79c56836323b570e76e22861572983" and "af335bac947d01d63480592526505bb67ee7dff3" have entirely different histories.
ecac90373c
...
af335bac94
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,8 +2,6 @@
|
|||||||
*.py[oc]
|
*.py[oc]
|
||||||
*.swp
|
*.swp
|
||||||
|
|
||||||
_buildid.py
|
|
||||||
|
|
||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
|
|
||||||
|
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
|||||||
UI_FILES = $(wildcard gui/*.ui)
|
UI_FILES = $(wildcard gui/*.ui)
|
||||||
TS_FILES = $(wildcard i18n/*.ts)
|
TS_FILES = $(wildcard i18n/*.ts)
|
||||||
PY_FILES = $(wildcard *.py) $(wildcard gui/*.py) $(wildcard luftdatentool/*.py)
|
PY_FILES = $(wildcard *.py) $(wildcard gui/*.py)
|
||||||
|
|
||||||
UI_COMPILED = $(UI_FILES:.ui=.py)
|
UI_COMPILED = $(UI_FILES:.ui=.py)
|
||||||
TS_COMPILED = $(TS_FILES:.ts=.qm)
|
TS_COMPILED = $(TS_FILES:.ts=.qm)
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>493</width>
|
<width>503</width>
|
||||||
<height>466</height>
|
<height>530</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -17,7 +17,7 @@
|
|||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>Luftdaten.info Flashing Tool (v{version})</string>
|
<string>Luftdaten.info Flashing Tool</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon">
|
<property name="windowIcon">
|
||||||
<iconset>
|
<iconset>
|
||||||
@ -32,73 +32,39 @@
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QFrame" name="globalMessage">
|
<widget class="QWidget" name="formWidget" native="true">
|
||||||
<property name="frameShape">
|
|
||||||
<enum>QFrame::StyledPanel</enum>
|
|
||||||
</property>
|
|
||||||
<property name="frameShadow">
|
|
||||||
<enum>QFrame::Raised</enum>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="globalMessageTitle">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>75</weight>
|
|
||||||
<bold>true</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="globalMessageText">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="openExternalLinks">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
|
||||||
<property name="layoutDirection">
|
|
||||||
<enum>Qt::LeftToRight</enum>
|
|
||||||
</property>
|
|
||||||
<property name="tabPosition">
|
|
||||||
<enum>QTabWidget::South</enum>
|
|
||||||
</property>
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="programmingTab">
|
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||||
<horstretch>0</horstretch>
|
<horstretch>0</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
<attribute name="title">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<string>Flashing</string>
|
<item row="0" column="0">
|
||||||
</attribute>
|
<widget class="QLabel" name="label">
|
||||||
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0,0,0,0,0,0,0,1">
|
<property name="text">
|
||||||
<item row="3" column="0">
|
<string>Board:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="boardBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_2">
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Firmware version:</string>
|
<string>Firmware version:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0" colspan="2">
|
<item row="1" column="1">
|
||||||
<widget class="QProgressBar" name="progressBar"/>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QComboBox" name="versionBox">
|
<widget class="QComboBox" name="versionBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
@ -111,7 +77,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0" colspan="2">
|
<item row="3" column="0" colspan="2">
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="uploadButton">
|
<widget class="QPushButton" name="uploadButton">
|
||||||
@ -138,24 +104,13 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="2" column="0" colspan="2">
|
||||||
<widget class="QComboBox" name="boardBox">
|
<widget class="QProgressBar" name="progressBar"/>
|
||||||
<property name="sizePolicy">
|
</item>
|
||||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
</layout>
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="0">
|
<item>
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Board:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="7" column="0" colspan="2">
|
|
||||||
<widget class="QWidget" name="expertForm" native="true">
|
<widget class="QWidget" name="expertForm" native="true">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||||
@ -196,153 +151,13 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="discoveryTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Discovery</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
|
||||||
<item row="3" column="0" colspan="2">
|
|
||||||
<widget class="QListWidget" name="discoveryList"/>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="0" colspan="2">
|
|
||||||
<widget class="QLabel" name="label_5">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<italic>true</italic>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Double-click to open configuration page.</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Sensors detected in local network:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QPushButton" name="discoveryRefreshButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Refresh</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="serialTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>Serial Monitor</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_4">
|
|
||||||
<item row="2" column="0">
|
|
||||||
<widget class="QTextEdit" name="serialTextEdit"/>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<widget class="QLabel" name="label_9">
|
|
||||||
<property name="text">
|
|
||||||
<string>In case of sensor issues, Serial Monitor can be used to review logs sent by the sensor over USB cable.</string>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QPushButton" name="serialConnectButton">
|
|
||||||
<property name="text">
|
|
||||||
<string>Connect</string>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="aboutTab">
|
|
||||||
<attribute name="title">
|
|
||||||
<string>About</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QGridLayout" name="gridLayout_3">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>12</number>
|
|
||||||
</property>
|
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QLabel" name="buildLabel">
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<weight>50</weight>
|
|
||||||
<bold>false</bold>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string><b>Luftdaten.info Flashing Tool</b><br/>Build {build_id}</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="0">
|
|
||||||
<widget class="QLabel" name="label_6">
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>64</width>
|
|
||||||
<height>64</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
<property name="pixmap">
|
|
||||||
<pixmap>../assets/logo.png</pixmap>
|
|
||||||
</property>
|
|
||||||
<property name="scaledContents">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="2" column="0" colspan="2">
|
|
||||||
<widget class="QLabel" name="label_8">
|
|
||||||
<property name="text">
|
|
||||||
<string><html><head/><body><p>Developed by <a href="https://inf.re/"><span style=" text-decoration: underline; color:#0000ff;">Piotr Dobrowolski</span></a>.</p><p>This software is released under the terms of MIT license. No warranty is provided.</p><p>For newest release see: <a href="https://d.inf.re/luftdaten/"><span style=" text-decoration: underline; color:#0000ff;">https://d.inf.re/luftdaten/</span></a></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="textFormat">
|
|
||||||
<enum>Qt::RichText</enum>
|
|
||||||
</property>
|
|
||||||
<property name="alignment">
|
|
||||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
|
||||||
</property>
|
|
||||||
<property name="wordWrap">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="openExternalLinks">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QMenuBar" name="menubar">
|
<widget class="QMenuBar" name="menubar">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>493</width>
|
<width>503</width>
|
||||||
<height>20</height>
|
<height>22</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -4,149 +4,94 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../luftdaten-tool.py" line="132"/>
|
<location filename="../luftdaten-tool.py" line="199"/>
|
||||||
<source>No boards found</source>
|
<source>No boards found</source>
|
||||||
<translation>Nie znaleziono płytki</translation>
|
<translation>Nie znaleziono płytki</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../luftdaten-tool.py" line="141"/>
|
<location filename="../luftdaten-tool.py" line="204"/>
|
||||||
<source>Others...</source>
|
<source>Others...</source>
|
||||||
<translation>Inne...</translation>
|
<translation>Inne...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../luftdaten-tool.py" line="170"/>
|
<location filename="../luftdaten-tool.py" line="233"/>
|
||||||
<source>No device selected.</source>
|
<source>No device selected.</source>
|
||||||
<translation>Nie wybrano urządzenia.</translation>
|
<translation>Nie wybrano urządzenia.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../luftdaten-tool.py" line="174"/>
|
<location filename="../luftdaten-tool.py" line="237"/>
|
||||||
<source>No version selected.</source>
|
<source>No version selected.</source>
|
||||||
<translation>Nie wybrano wersji.</translation>
|
<translation>Nie wybrano wersji.</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../gui/mainwindow.py" line="226"/>
|
<location filename="../gui/mainwindow.py" line="131"/>
|
||||||
<source>Board:</source>
|
<source>Board:</source>
|
||||||
<translation>Płytka:</translation>
|
<translation>Płytka:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../gui/mainwindow.py" line="223"/>
|
<location filename="../gui/mainwindow.py" line="132"/>
|
||||||
<source>Firmware version:</source>
|
<source>Firmware version:</source>
|
||||||
<translation>Wersja oprogramowania:</translation>
|
<translation>Wersja oprogramowania:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../gui/mainwindow.py" line="224"/>
|
<location filename="../gui/mainwindow.py" line="133"/>
|
||||||
<source>Upload</source>
|
<source>Upload</source>
|
||||||
<translation>Wgraj</translation>
|
<translation>Wgraj</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../gui/mainwindow.py" line="225"/>
|
<location filename="../gui/mainwindow.py" line="134"/>
|
||||||
<source>Expert mode</source>
|
<source>Expert mode</source>
|
||||||
<translation>Tryb eksperta</translation>
|
<translation>Tryb eksperta</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../gui/mainwindow.py" line="227"/>
|
<location filename="../gui/mainwindow.py" line="135"/>
|
||||||
<source>Baudrate:</source>
|
<source>Baudrate:</source>
|
||||||
<translation>Prędkość portu:</translation>
|
<translation>Prędkość portu:</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../luftdaten-tool.py" line="189"/>
|
<location filename="../luftdaten-tool.py" line="252"/>
|
||||||
<source>Invalid version / file does not exist</source>
|
<source>Invalid version / file does not exist</source>
|
||||||
<translation>Błędna wersja / plik nie istnieje</translation>
|
<translation>Błędna wersja / plik nie istnieje</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../luftdaten-tool.py" line="194"/>
|
<location filename="../luftdaten-tool.py" line="257"/>
|
||||||
<source>Work in progess...</source>
|
<source>Work in progess...</source>
|
||||||
<translation>Praca w toku...</translation>
|
<translation>Praca w toku...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../luftdaten-tool.py" line="221"/>
|
<location filename="../luftdaten-tool.py" line="284"/>
|
||||||
<source>Downloading...</source>
|
<source>Downloading...</source>
|
||||||
<translation>Pobieranie...</translation>
|
<translation>Pobieranie...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../luftdaten-tool.py" line="231"/>
|
<location filename="../luftdaten-tool.py" line="296"/>
|
||||||
<source>Connecting...</source>
|
<source>Connecting...</source>
|
||||||
<translation>Łączenie...</translation>
|
<translation>Łączenie...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../luftdaten-tool.py" line="236"/>
|
<location filename="../luftdaten-tool.py" line="301"/>
|
||||||
<source>Connected. Chip type: {chip_type}</source>
|
<source>Connected. Chip type: {chip_type}</source>
|
||||||
<translation>Połączono. Typ układu: {chip_type}</translation>
|
<translation>Połączono. Typ układu: {chip_type}</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../luftdaten-tool.py" line="254"/>
|
<location filename="../luftdaten-tool.py" line="319"/>
|
||||||
<source>Writing at 0x{address:08x}...</source>
|
<source>Writing at 0x{address:08x}...</source>
|
||||||
<translation>Zapisywanie pod adresem 0x{address:08x}...</translation>
|
<translation>Zapisywanie pod adresem 0x{address:08x}...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../luftdaten-tool.py" line="265"/>
|
<location filename="../luftdaten-tool.py" line="330"/>
|
||||||
<source>Finished in {time:.2f} seconds. Sensor ID: {sensor_id}</source>
|
<source>Finished in {time:.2f} seconds. Sensor ID: {sensor_id}</source>
|
||||||
<translation>Zakończono w {time:.2f} sekundy. ID sensora: {sensor_id}</translation>
|
<translation>Zakończono w {time:.2f} sekundy. ID sensora: {sensor_id}</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../gui/mainwindow.py" line="236"/>
|
<location filename="../gui/mainwindow.py" line="130"/>
|
||||||
<source>Luftdaten.info Flashing Tool</source>
|
<source>Luftdaten.info Flashing Tool</source>
|
||||||
<translation>Luftdaten.info Flashing Tool</translation>
|
<translation>Luftdaten.info Flashing Tool</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../luftdaten-tool.py" line="52"/>
|
<location filename="../luftdaten-tool.py" line="138"/>
|
||||||
<source>Loading firmware list...</source>
|
<source>Loading firmware list...</source>
|
||||||
<translation>Ładowanie wersji oprogramowania...</translation>
|
<translation>Ładowanie wersji oprogramowania...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="../luftdaten-tool.py" line="132"/>
|
|
||||||
<source>Have you installed <a href="{drivers_url}">the drivers</a>?</source>
|
|
||||||
<translation>Czy zainstalowałeś <a href="{drivers_url}">sterowniki</a>?</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../gui/mainwindow.py" line="228"/>
|
|
||||||
<source>Flashing</source>
|
|
||||||
<translation>Programowanie</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../gui/mainwindow.py" line="229"/>
|
|
||||||
<source>Double-click to open configuration page.</source>
|
|
||||||
<translation>Naciśnij dwukrotnie aby otworzyć stronę konfiguracji.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../gui/mainwindow.py" line="230"/>
|
|
||||||
<source>Sensors detected in local network:</source>
|
|
||||||
<translation>Sensory wykryte w sieci lokalnej:</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../gui/mainwindow.py" line="231"/>
|
|
||||||
<source>Refresh</source>
|
|
||||||
<translation>Odśwież</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../gui/mainwindow.py" line="232"/>
|
|
||||||
<source>Discovery</source>
|
|
||||||
<translation>Wykrywanie</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../gui/mainwindow.py" line="233"/>
|
|
||||||
<source>In case of sensor issues, Serial Monitor can be used to review logs sent by the sensor over USB cable.</source>
|
|
||||||
<translation>W przypadku problemów z sensorem, Serial Monitor pozwala na przejrzenie stanu urządzenia przez kabel USB.</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../gui/mainwindow.py" line="234"/>
|
|
||||||
<source>Connect</source>
|
|
||||||
<translation>Połącz</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../gui/mainwindow.py" line="235"/>
|
|
||||||
<source>Serial Monitor</source>
|
|
||||||
<translation>Serial Monitor</translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../gui/mainwindow.py" line="237"/>
|
|
||||||
<source><html><head/><body><p>Developed by <a href="https://inf.re/"><span style=" text-decoration: underline; color:#0000ff;">Piotr Dobrowolski</span></a>.</p><p>This software is released under the terms of MIT license. No warranty is provided.</p><p>For newest release see: <a href="https://d.inf.re/luftdaten/"><span style=" text-decoration: underline; color:#0000ff;">https://d.inf.re/luftdaten/</span></a></p></body></html></source>
|
|
||||||
<translation><html><head/><body><p>Wykonane przez <a href="https://inf.re/"><span style=" text-decoration: underline; color:#0000ff;">Piotr Dobrowolski</span></a>.</p><p>Ten program wypuszczony jest na warunkach licencji MIT. Brak gwarancji.</p><p>Najnowszą wersję znajdziesz na: <a href="https://d.inf.re/luftdaten/"><span style=" text-decoration: underline; color:#0000ff;">https://d.inf.re/luftdaten/</span></a></p></body></html></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../gui/mainwindow.py" line="238"/>
|
|
||||||
<source>About</source>
|
|
||||||
<translation>O programie</translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
</context>
|
||||||
</TS>
|
</TS>
|
||||||
|
@ -2,38 +2,123 @@
|
|||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
|
import re
|
||||||
import time
|
import time
|
||||||
import tempfile
|
import tempfile
|
||||||
import hashlib
|
import hashlib
|
||||||
import zlib
|
import zlib
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
import serial
|
||||||
|
import serial.tools.list_ports
|
||||||
import requests
|
import requests
|
||||||
from esptool import ESPLoader
|
from esptool import ESPLoader
|
||||||
|
from PyQt5 import QtGui, QtCore, QtWidgets
|
||||||
import luftdatentool
|
|
||||||
from luftdatentool.qtvariant import QtGui, QtCore, QtWidgets
|
|
||||||
from luftdatentool.utils import QuickThread
|
|
||||||
from luftdatentool.workers import PortDetectThread, FirmwareListThread, \
|
|
||||||
ZeroconfDiscoveryThread
|
|
||||||
|
|
||||||
from gui import mainwindow
|
from gui import mainwindow
|
||||||
|
|
||||||
from luftdatentool.consts import UPDATE_REPOSITORY, ALLOWED_PROTO, \
|
# Firmware update repository
|
||||||
PREFERED_PORTS, ROLE_DEVICE, DRIVERS_URL
|
UPDATE_REPOSITORY = 'https://www.madavi.de/sensor/update/data/'
|
||||||
|
|
||||||
|
# URI prefixes (protocol parts, essentially) to be downloaded using requests
|
||||||
|
ALLOWED_PROTO = ('http://', 'https://')
|
||||||
|
|
||||||
|
# vid/pid pairs of known NodeMCU/ESP8266 development boards
|
||||||
|
PREFERED_PORTS = [
|
||||||
|
# CH341
|
||||||
|
(0x1A86, 0x7523),
|
||||||
|
|
||||||
|
# CP2102
|
||||||
|
(0x10c4, 0xea60),
|
||||||
|
]
|
||||||
|
|
||||||
|
ROLE_DEVICE = QtCore.Qt.UserRole + 1
|
||||||
|
|
||||||
if getattr(sys, 'frozen', False):
|
if getattr(sys, 'frozen', False):
|
||||||
RESOURCES_PATH = sys._MEIPASS
|
RESOURCES_PATH = sys._MEIPASS
|
||||||
else:
|
else:
|
||||||
RESOURCES_PATH = os.path.dirname(os.path.realpath(__file__))
|
RESOURCES_PATH = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
# FIXME move this into something like qtvariant.py
|
||||||
|
QtCore.Signal = QtCore.pyqtSignal
|
||||||
|
QtCore.Slot = QtCore.pyqtSlot
|
||||||
|
|
||||||
|
file_index_re = re.compile(r'<a href="([^"]*)">([^<]*)</a>')
|
||||||
|
|
||||||
|
|
||||||
|
def indexof(path):
|
||||||
|
"""Returns list of filenames parsed off "Index of" page"""
|
||||||
|
resp = requests.get(path)
|
||||||
|
return [a for a, b in file_index_re.findall(resp.text) if a == b]
|
||||||
|
|
||||||
|
|
||||||
|
class QuickThread(QtCore.QThread):
|
||||||
|
"""Provides similar API to threading.Thread but with additional error
|
||||||
|
reporting based on Qt Signals"""
|
||||||
|
def __init__(self, parent=None, target=None, args=None, kwargs=None,
|
||||||
|
error=None):
|
||||||
|
super(QuickThread, self).__init__(parent)
|
||||||
|
self.target = target
|
||||||
|
self.args = args or []
|
||||||
|
self.kwargs = kwargs or {}
|
||||||
|
self.error = error
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
try:
|
||||||
|
self.target(*self.args, **self.kwargs)
|
||||||
|
except Exception as exc:
|
||||||
|
if self.error:
|
||||||
|
self.error.emit(str(exc))
|
||||||
|
# raise here causes windows builds to just die. ¯\_(ツ)_/¯
|
||||||
|
logging.exception('Unhandled exception')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def wrap(cls, func):
|
||||||
|
"""Decorator that wraps function in a QThread. Calling resulting
|
||||||
|
function starts and creates QThread, with parent set to [self]"""
|
||||||
|
def wrapped(*args, **kwargs):
|
||||||
|
th = cls(parent=args[0], target=func, args=args, kwargs=kwargs,
|
||||||
|
error=kwargs.pop('error', None))
|
||||||
|
func._th = th
|
||||||
|
th.start()
|
||||||
|
|
||||||
|
return th
|
||||||
|
|
||||||
|
wrapped.running = lambda: (hasattr(func, '_th') and
|
||||||
|
func._th.isRunning())
|
||||||
|
return wrapped
|
||||||
|
|
||||||
|
|
||||||
|
class PortDetectThread(QtCore.QThread):
|
||||||
|
interval = 1.0
|
||||||
|
portsUpdate = QtCore.Signal([list])
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
"""Checks list of available ports and emits signal when necessary"""
|
||||||
|
|
||||||
|
ports = []
|
||||||
|
while True:
|
||||||
|
new_ports = serial.tools.list_ports.comports()
|
||||||
|
|
||||||
|
if [p.name for p in ports] != [p.name for p in new_ports]:
|
||||||
|
self.portsUpdate.emit(new_ports)
|
||||||
|
|
||||||
|
time.sleep(self.interval)
|
||||||
|
|
||||||
|
ports = new_ports
|
||||||
|
|
||||||
|
|
||||||
|
class FirmwareListThread(QtCore.QThread):
|
||||||
|
onFirmware = QtCore.Signal([list])
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
"""Downloads list of available firmware updates in separate thread."""
|
||||||
|
self.onFirmware.emit(list(indexof(UPDATE_REPOSITORY)))
|
||||||
|
|
||||||
class MainWindow(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
class MainWindow(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
||||||
uploadProgress = QtCore.Signal([str, int])
|
signal = QtCore.Signal([str, int])
|
||||||
errorSignal = QtCore.Signal([str])
|
errorSignal = QtCore.Signal([str])
|
||||||
uploadThread = None
|
uploadThread = None
|
||||||
zeroconf_discovery = None
|
|
||||||
boards_detected = False
|
|
||||||
|
|
||||||
def __init__(self, parent=None, app=None):
|
def __init__(self, parent=None, app=None):
|
||||||
super(MainWindow, self).__init__(parent)
|
super(MainWindow, self).__init__(parent)
|
||||||
@ -46,41 +131,26 @@ class MainWindow(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
os.chdir(oldcwd)
|
os.chdir(oldcwd)
|
||||||
|
|
||||||
self.app = app
|
self.app = app
|
||||||
|
|
||||||
self.translator = QtCore.QTranslator()
|
self.translator = QtCore.QTranslator()
|
||||||
|
|
||||||
self.i18n_init(QtCore.QLocale.system())
|
self.i18n_init(QtCore.QLocale.system())
|
||||||
|
|
||||||
self.statusbar.showMessage(self.tr("Loading firmware list..."))
|
self.statusbar.showMessage(self.tr("Loading firmware list..."))
|
||||||
|
|
||||||
self.firmware_list = FirmwareListThread()
|
self.firmware_list = FirmwareListThread()
|
||||||
self.firmware_list.listLoaded.connect(self.populate_versions)
|
self.firmware_list.onFirmware.connect(self.populate_versions)
|
||||||
self.firmware_list.error.connect(self.on_work_error)
|
|
||||||
self.firmware_list.start()
|
self.firmware_list.start()
|
||||||
|
|
||||||
self.port_detect = PortDetectThread()
|
self.port_detect = PortDetectThread()
|
||||||
self.port_detect.portsUpdate.connect(self.populate_boards)
|
self.port_detect.portsUpdate.connect(self.populate_boards)
|
||||||
self.port_detect.error.connect(self.on_work_error)
|
|
||||||
self.port_detect.start()
|
self.port_detect.start()
|
||||||
|
|
||||||
self.discovery_start()
|
|
||||||
|
|
||||||
self.globalMessage.hide()
|
|
||||||
|
|
||||||
# Hide WIP GUI parts...
|
|
||||||
self.on_expertModeBox_clicked()
|
self.on_expertModeBox_clicked()
|
||||||
self.expertModeBox.hide()
|
|
||||||
self.tabWidget.removeTab(self.tabWidget.indexOf(self.serialTab))
|
|
||||||
|
|
||||||
self.uploadProgress.connect(self.on_work_update)
|
self.signal.connect(self.on_work_update)
|
||||||
self.errorSignal.connect(self.on_work_error)
|
self.errorSignal.connect(self.on_work_error)
|
||||||
|
|
||||||
self.cachedir = tempfile.TemporaryDirectory()
|
self.cachedir = tempfile.TemporaryDirectory()
|
||||||
|
|
||||||
def show_global_message(self, title, message):
|
|
||||||
self.globalMessage.show()
|
|
||||||
self.globalMessageTitle.setText(title)
|
|
||||||
self.globalMessageText.setText(message)
|
|
||||||
|
|
||||||
def on_work_update(self, status, progress):
|
def on_work_update(self, status, progress):
|
||||||
self.statusbar.showMessage(status)
|
self.statusbar.showMessage(status)
|
||||||
self.progressBar.setValue(progress)
|
self.progressBar.setValue(progress)
|
||||||
@ -88,21 +158,6 @@ class MainWindow(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
def on_work_error(self, message):
|
def on_work_error(self, message):
|
||||||
self.statusbar.showMessage(message)
|
self.statusbar.showMessage(message)
|
||||||
|
|
||||||
@property
|
|
||||||
def version(self):
|
|
||||||
return luftdatentool.__version__
|
|
||||||
|
|
||||||
@property
|
|
||||||
def build_id(self):
|
|
||||||
try:
|
|
||||||
from luftdatentool._buildid import commit, builddate
|
|
||||||
except ImportError:
|
|
||||||
import datetime
|
|
||||||
commit = 'devel'
|
|
||||||
builddate = datetime.datetime.now().strftime('%Y%m%d')
|
|
||||||
|
|
||||||
return '{}-{}/{}'.format(self.version, commit, builddate)
|
|
||||||
|
|
||||||
def i18n_init(self, locale):
|
def i18n_init(self, locale):
|
||||||
"""Initializes i18n to specified QLocale"""
|
"""Initializes i18n to specified QLocale"""
|
||||||
|
|
||||||
@ -113,13 +168,6 @@ class MainWindow(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
self.app.installTranslator(self.translator)
|
self.app.installTranslator(self.translator)
|
||||||
self.retranslateUi(self)
|
self.retranslateUi(self)
|
||||||
|
|
||||||
def retranslateUi(self, win):
|
|
||||||
super(MainWindow, self).retranslateUi(win)
|
|
||||||
|
|
||||||
win.setWindowTitle(win.windowTitle().format(
|
|
||||||
version=self.version))
|
|
||||||
win.buildLabel.setText(win.buildLabel.text().format(
|
|
||||||
build_id=self.build_id))
|
|
||||||
def populate_versions(self, files):
|
def populate_versions(self, files):
|
||||||
"""Loads available firmware versions into versionbox widget"""
|
"""Loads available firmware versions into versionbox widget"""
|
||||||
|
|
||||||
@ -152,17 +200,6 @@ class MainWindow(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
sep.setEnabled(False)
|
sep.setEnabled(False)
|
||||||
self.boardBox.model().appendRow(sep)
|
self.boardBox.model().appendRow(sep)
|
||||||
|
|
||||||
# No prefered boards has been found so far and there is a
|
|
||||||
# suggested driver download URL available
|
|
||||||
if not self.boards_detected and DRIVERS_URL:
|
|
||||||
self.show_global_message(
|
|
||||||
self.tr('No boards found'),
|
|
||||||
self.tr('Have you installed <a href="{drivers_url}">'
|
|
||||||
'the drivers</a>?').format(drivers_url=DRIVERS_URL))
|
|
||||||
else:
|
|
||||||
self.globalMessage.hide()
|
|
||||||
self.boards_detected = True
|
|
||||||
|
|
||||||
if others:
|
if others:
|
||||||
sep = QtGui.QStandardItem(self.tr('Others...'))
|
sep = QtGui.QStandardItem(self.tr('Others...'))
|
||||||
sep.setEnabled(False)
|
sep.setEnabled(False)
|
||||||
@ -220,7 +257,7 @@ class MainWindow(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
self.statusbar.showMessage(self.tr("Work in progess..."))
|
self.statusbar.showMessage(self.tr("Work in progess..."))
|
||||||
return
|
return
|
||||||
|
|
||||||
self.flash_board(self.uploadProgress, device, binary_uri,
|
self.flash_board(self.signal, device, binary_uri,
|
||||||
error=self.errorSignal)
|
error=self.errorSignal)
|
||||||
|
|
||||||
def cache_download(self, progress, binary_uri):
|
def cache_download(self, progress, binary_uri):
|
||||||
@ -254,6 +291,8 @@ class MainWindow(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
if binary_uri.startswith(ALLOWED_PROTO):
|
if binary_uri.startswith(ALLOWED_PROTO):
|
||||||
binary_uri = self.cache_download(progress, binary_uri)
|
binary_uri = self.cache_download(progress, binary_uri)
|
||||||
|
|
||||||
|
print(binary_uri)
|
||||||
|
|
||||||
progress.emit(self.tr('Connecting...'), 0)
|
progress.emit(self.tr('Connecting...'), 0)
|
||||||
|
|
||||||
init_baud = min(ESPLoader.ESP_ROM_BAUD, baudrate)
|
init_baud = min(ESPLoader.ESP_ROM_BAUD, baudrate)
|
||||||
@ -295,36 +334,9 @@ class MainWindow(QtWidgets.QMainWindow, mainwindow.Ui_MainWindow):
|
|||||||
@QtCore.Slot()
|
@QtCore.Slot()
|
||||||
def on_expertModeBox_clicked(self):
|
def on_expertModeBox_clicked(self):
|
||||||
self.expertForm.setVisible(self.expertModeBox.checkState())
|
self.expertForm.setVisible(self.expertModeBox.checkState())
|
||||||
#self.centralwidget.setFixedHeight(
|
self.centralwidget.setFixedHeight(
|
||||||
# self.centralwidget.sizeHint().height())
|
self.centralwidget.sizeHint().height())
|
||||||
#self.setFixedHeight(self.sizeHint().height())
|
self.setFixedHeight(self.sizeHint().height())
|
||||||
|
|
||||||
# Zeroconf page
|
|
||||||
def discovery_start(self):
|
|
||||||
if self.zeroconf_discovery:
|
|
||||||
self.zeroconf_discovery.stop()
|
|
||||||
|
|
||||||
self.zeroconf_discovery = ZeroconfDiscoveryThread()
|
|
||||||
self.zeroconf_discovery.deviceDiscovered.connect(
|
|
||||||
self.on_zeroconf_discovered)
|
|
||||||
self.zeroconf_discovery.start()
|
|
||||||
|
|
||||||
|
|
||||||
def on_zeroconf_discovered(self, name, address, info):
|
|
||||||
"""Called on every zeroconf discovered device"""
|
|
||||||
if name.startswith('Feinstaubsensor'):
|
|
||||||
item = QtWidgets.QListWidgetItem('{}: {}'.format(address, name.split('.')[0]))
|
|
||||||
item.setData(ROLE_DEVICE, 'http://{}:{}'.format(address, info.port))
|
|
||||||
self.discoveryList.addItem(item)
|
|
||||||
|
|
||||||
@QtCore.Slot(QtWidgets.QListWidgetItem)
|
|
||||||
def on_discoveryList_itemDoubleClicked(self, index):
|
|
||||||
QtGui.QDesktopServices.openUrl(QtCore.QUrl(index.data(ROLE_DEVICE)))
|
|
||||||
|
|
||||||
@QtCore.Slot()
|
|
||||||
def on_discoveryRefreshButton_clicked(self):
|
|
||||||
self.discoveryList.clear()
|
|
||||||
self.discovery_start()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@ -2,16 +2,6 @@
|
|||||||
|
|
||||||
block_cipher = None
|
block_cipher = None
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
commit = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']).strip().decode('utf-8')
|
|
||||||
builddate = datetime.datetime.now().strftime('%Y%m%d')
|
|
||||||
|
|
||||||
with open('luftdatentool/_buildid.py', 'w') as fd:
|
|
||||||
fd.write('''# This file is autogenerated in luftdaten-tool.spec file
|
|
||||||
commit = "{commit}"
|
|
||||||
builddate = "{builddate}"'''.format(commit=commit, builddate=builddate))
|
|
||||||
|
|
||||||
a = Analysis(['luftdaten-tool.py'],
|
a = Analysis(['luftdaten-tool.py'],
|
||||||
pathex=['.'],
|
pathex=['.'],
|
||||||
|
@ -1 +0,0 @@
|
|||||||
__version__ = '0.2'
|
|
@ -1,28 +0,0 @@
|
|||||||
import sys
|
|
||||||
|
|
||||||
from .qtvariant import QtCore
|
|
||||||
|
|
||||||
|
|
||||||
# Firmware update repository
|
|
||||||
UPDATE_REPOSITORY = 'https://www.madavi.de/sensor/update/data/'
|
|
||||||
|
|
||||||
# URI prefixes (protocol parts, essentially) to be downloaded using requests
|
|
||||||
ALLOWED_PROTO = ('http://', 'https://')
|
|
||||||
|
|
||||||
# vid/pid pairs of known NodeMCU/ESP8266 development boards
|
|
||||||
PREFERED_PORTS = [
|
|
||||||
# CH341
|
|
||||||
(0x1A86, 0x7523),
|
|
||||||
|
|
||||||
# CP2102
|
|
||||||
(0x10c4, 0xea60),
|
|
||||||
]
|
|
||||||
|
|
||||||
ROLE_DEVICE = QtCore.Qt.UserRole + 1
|
|
||||||
|
|
||||||
if sys.platform.startswith('darwin'):
|
|
||||||
DRIVERS_URL = 'http://www.wch.cn/downloads/CH341SER_MAC_ZIP.html'
|
|
||||||
elif sys.platform.startswith(('cygwin', 'win32')):
|
|
||||||
DRIVERS_URL = 'http://www.wch.cn/downloads/CH341SER_ZIP.html'
|
|
||||||
else:
|
|
||||||
DRIVERS_URL = None
|
|
@ -1,8 +0,0 @@
|
|||||||
"""PyQt5 & PySide2 compatiblity layer stub. This will be updated when PySide2
|
|
||||||
gets mature enough"""
|
|
||||||
|
|
||||||
from PyQt5 import QtGui, QtCore, QtWidgets
|
|
||||||
|
|
||||||
# Replace nonsense prefixes
|
|
||||||
QtCore.Signal = QtCore.pyqtSignal
|
|
||||||
QtCore.Slot = QtCore.pyqtSlot
|
|
@ -1,56 +0,0 @@
|
|||||||
import requests
|
|
||||||
import re
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from .qtvariant import QtCore
|
|
||||||
|
|
||||||
|
|
||||||
file_index_re = re.compile(r'<a href="([^"]*)">([^<]*)</a>')
|
|
||||||
|
|
||||||
|
|
||||||
def indexof(path):
|
|
||||||
"""Returns list of filenames parsed off "Index of" page"""
|
|
||||||
resp = requests.get(path)
|
|
||||||
return [a for a, b in file_index_re.findall(resp.text) if a == b]
|
|
||||||
|
|
||||||
|
|
||||||
class QuickThread(QtCore.QThread):
|
|
||||||
error = QtCore.Signal([str])
|
|
||||||
|
|
||||||
"""Provides similar API to threading.Thread but with additional error
|
|
||||||
reporting based on Qt Signals"""
|
|
||||||
def __init__(self, parent=None, target=None, args=None, kwargs=None,
|
|
||||||
error=None):
|
|
||||||
super(QuickThread, self).__init__(parent)
|
|
||||||
self.target = target or self.target
|
|
||||||
self.args = args or []
|
|
||||||
self.kwargs = kwargs or {}
|
|
||||||
self.error = error or self.error
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
try:
|
|
||||||
self.target(*self.args, **self.kwargs)
|
|
||||||
except Exception as exc:
|
|
||||||
if self.error:
|
|
||||||
self.error.emit(str(exc))
|
|
||||||
# raise here causes windows builds to just die. ¯\_(ツ)_/¯
|
|
||||||
logging.exception('Unhandled exception')
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def wrap(cls, func):
|
|
||||||
"""Decorator that wraps function in a QThread. Calling resulting
|
|
||||||
function starts and creates QThread, with parent set to [self]"""
|
|
||||||
def wrapped(*args, **kwargs):
|
|
||||||
th = cls(parent=args[0], target=func, args=args, kwargs=kwargs,
|
|
||||||
error=kwargs.pop('error', None))
|
|
||||||
func._th = th
|
|
||||||
th.start()
|
|
||||||
|
|
||||||
return th
|
|
||||||
|
|
||||||
wrapped.running = lambda: (hasattr(func, '_th') and
|
|
||||||
func._th.isRunning())
|
|
||||||
return wrapped
|
|
||||||
|
|
||||||
def target(self):
|
|
||||||
pass
|
|
@ -1,60 +0,0 @@
|
|||||||
import time
|
|
||||||
import socket
|
|
||||||
|
|
||||||
import serial
|
|
||||||
import serial.tools.list_ports
|
|
||||||
import zeroconf
|
|
||||||
|
|
||||||
from .qtvariant import QtCore
|
|
||||||
from .utils import indexof, QuickThread
|
|
||||||
from .consts import UPDATE_REPOSITORY
|
|
||||||
|
|
||||||
|
|
||||||
class PortDetectThread(QuickThread):
|
|
||||||
interval = 1.0
|
|
||||||
portsUpdate = QtCore.Signal([list])
|
|
||||||
|
|
||||||
def target(self):
|
|
||||||
"""Checks list of available ports and emits signal when necessary"""
|
|
||||||
|
|
||||||
ports = None
|
|
||||||
while True:
|
|
||||||
new_ports = serial.tools.list_ports.comports()
|
|
||||||
|
|
||||||
if ports is None or [p.name for p in ports] != [p.name for p in new_ports]:
|
|
||||||
self.portsUpdate.emit(new_ports)
|
|
||||||
|
|
||||||
time.sleep(self.interval)
|
|
||||||
|
|
||||||
ports = new_ports
|
|
||||||
|
|
||||||
|
|
||||||
class FirmwareListThread(QuickThread):
|
|
||||||
listLoaded = QtCore.Signal([list])
|
|
||||||
|
|
||||||
def target(self):
|
|
||||||
"""Downloads list of available firmware updates in separate thread."""
|
|
||||||
self.listLoaded.emit(list(indexof(UPDATE_REPOSITORY)))
|
|
||||||
|
|
||||||
|
|
||||||
class ZeroconfDiscoveryThread(QuickThread):
|
|
||||||
deviceDiscovered = QtCore.Signal(str, str, object)
|
|
||||||
browser = None
|
|
||||||
|
|
||||||
def target(self):
|
|
||||||
"""This thread scans for Bonjour/mDNS devices and emits
|
|
||||||
deviceDiscovered signal with its name, address and info object"""
|
|
||||||
self.zc = zeroconf.Zeroconf()
|
|
||||||
self.browser = zeroconf.ServiceBrowser(self.zc, "_http._tcp.local.",
|
|
||||||
handlers=[self.on_state_change])
|
|
||||||
while True:
|
|
||||||
time.sleep(0.5)
|
|
||||||
|
|
||||||
def on_state_change(self, zeroconf, service_type, name, state_change):
|
|
||||||
info = zeroconf.get_service_info(service_type, name)
|
|
||||||
if info:
|
|
||||||
self.deviceDiscovered.emit(name, socket.inet_ntoa(info.address), info)
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
if self.browser:
|
|
||||||
self.browser.cancel()
|
|
@ -6,7 +6,6 @@ esptool==2.5.0
|
|||||||
future==0.16.0
|
future==0.16.0
|
||||||
idna==2.7
|
idna==2.7
|
||||||
macholib==1.11
|
macholib==1.11
|
||||||
netifaces==0.10.7
|
|
||||||
pefile==2018.8.8
|
pefile==2018.8.8
|
||||||
pyaes==1.6.1
|
pyaes==1.6.1
|
||||||
https://github.com/pyinstaller/pyinstaller/archive/bbf964c6b89ca33823031fa7ed277c0269192b3e.zip#egg=PyInstaller
|
https://github.com/pyinstaller/pyinstaller/archive/bbf964c6b89ca33823031fa7ed277c0269192b3e.zip#egg=PyInstaller
|
||||||
@ -15,4 +14,3 @@ PyQt5-sip==4.19.12
|
|||||||
pyserial==3.4
|
pyserial==3.4
|
||||||
requests==2.19.1
|
requests==2.19.1
|
||||||
urllib3==1.23
|
urllib3==1.23
|
||||||
zeroconf==0.20.0
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user