Compare commits
9 Commits
nightly-0.
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| efde35130b | |||
| a31e01d28c | |||
| 7a43698ecc | |||
| 6b12bfb321 | |||
| 823cbfe1a9 | |||
| ce416f3b9a | |||
| 67c013f4ff | |||
| 40f85b1eb6 | |||
| 54ce101f99 |
@@ -85,34 +85,18 @@ jobs:
|
||||
git config user.name "gitea-actions"
|
||||
git config user.email "actions@it-drui.de"
|
||||
|
||||
# Letzten stabilen Release-Tag finden (v* ohne nightly) als Changelog-Basis
|
||||
git fetch --tags origin 2>/dev/null || true
|
||||
PREV_TAG=$(git tag | grep -E '^v[0-9]+\.' | sort -V | tail -1)
|
||||
# Fallback: letzter nightly-Tag
|
||||
[ -z "$PREV_TAG" ] && PREV_TAG=$(git tag | grep '^nightly-' | sort | tail -1)
|
||||
|
||||
# Commits seit letztem stabilen Tag — chore/ci-Commits herausfiltern
|
||||
if [ -n "$PREV_TAG" ]; then
|
||||
COMMITS=$(git log "${PREV_TAG}..HEAD" --pretty=format:"- %s" --no-merges 2>/dev/null \
|
||||
| grep -v '^- chore: nightly' \
|
||||
| grep -v '^- ci:' \
|
||||
|| true)
|
||||
else
|
||||
COMMITS=$(git log --pretty=format:"- %s" --no-merges -30 2>/dev/null \
|
||||
| grep -v '^- chore: nightly' \
|
||||
| grep -v '^- ci:' \
|
||||
|| true)
|
||||
fi
|
||||
[ -z "$COMMITS" ] && COMMITS="- Automatischer Nightly-Build (keine neuen Features seit ${PREV_TAG})"
|
||||
|
||||
# Body in Temp-Datei (vermeidet YAML-Probleme mit Sonderzeichen wie > oder ```)
|
||||
# Changelog aus CHANGES.md lesen (wird von release.sh aus dem Dev-Repo generiert)
|
||||
BODY_FILE=$(mktemp)
|
||||
printf '## KX-Bridge %s -- Nightly Build\n\n' "$VERSION" > "$BODY_FILE"
|
||||
printf '[experimentell] Ungetestete Features, nur fuer Tester geeignet.\n\n' >> "$BODY_FILE"
|
||||
printf '### Aenderungen seit `%s`\n\n' "${PREV_TAG:-erstem Commit}" >> "$BODY_FILE"
|
||||
printf '%s\n\n---\n\n' "$COMMITS" >> "$BODY_FILE"
|
||||
printf '### Docker-Image aktualisieren\n\n```bash\ndocker compose pull && docker compose up -d\n```\n\n' >> "$BODY_FILE"
|
||||
printf 'Image-Tag: `gitea.it-drui.de/viewit/kx-bridge:nightly`\n' >> "$BODY_FILE"
|
||||
if [ -f CHANGES.md ]; then
|
||||
cat CHANGES.md > "$BODY_FILE"
|
||||
else
|
||||
# Fallback falls CHANGES.md fehlt
|
||||
printf '## KX-Bridge %s -- Nightly Build\n\n' "$VERSION" > "$BODY_FILE"
|
||||
printf '[experimentell] Ungetestete Features, nur fuer Tester geeignet.\n\n' >> "$BODY_FILE"
|
||||
printf '- Automatischer Nightly-Build\n\n---\n\n' >> "$BODY_FILE"
|
||||
printf '### Docker-Image aktualisieren\n\n```bash\ndocker compose pull && docker compose up -d\n```\n\n' >> "$BODY_FILE"
|
||||
printf 'Image-Tag: `gitea.it-drui.de/viewit/kx-bridge:nightly`\n' >> "$BODY_FILE"
|
||||
fi
|
||||
|
||||
# Tag setzen
|
||||
git tag -f "$TAG"
|
||||
|
||||
@@ -3,7 +3,7 @@ name: Stable Release
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
release:
|
||||
@@ -56,9 +56,10 @@ jobs:
|
||||
echo "${{ secrets.REGISTRY_TOKEN }}" | \
|
||||
docker login gitea.it-drui.de -u "${{ secrets.REGISTRY_USER }}" --password-stdin
|
||||
|
||||
# Strip fuehrendes 'v' fuer den Image-Tag (VERSION-Datei hat kein 'v').
|
||||
- name: Build & push (amd64 + arm64)
|
||||
run: |
|
||||
VERSION="${GITHUB_REF#refs/tags/}"
|
||||
VERSION="${GITHUB_REF#refs/tags/v}"
|
||||
docker buildx build \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
@@ -68,20 +69,6 @@ jobs:
|
||||
-t "gitea.it-drui.de/viewit/kx-bridge:${VERSION}" \
|
||||
.
|
||||
|
||||
- name: Create Gitea Release
|
||||
env:
|
||||
GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
run: |
|
||||
VERSION="${GITHUB_REF#refs/tags/}"
|
||||
CHANGELOG=$(awk "/^## \[${VERSION}\]/{found=1; next} found && /^## \[/{exit} found{print}" CHANGELOG.md || echo "")
|
||||
curl -s -X POST \
|
||||
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"https://gitea.it-drui.de/api/v1/repos/viewit/KX-Bridge-Release/releases" \
|
||||
-d "{
|
||||
\"tag_name\": \"${VERSION}\",
|
||||
\"name\": \"KX-Bridge ${VERSION}\",
|
||||
\"body\": $(echo "$CHANGELOG" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))'),
|
||||
\"draft\": false,
|
||||
\"prerelease\": false
|
||||
}"
|
||||
# Hinweis: Das Gitea-Release (inkl. englischem Auto-Changelog + Binaries als
|
||||
# Assets) erstellt release.sh synchron, da es die lokal via CodeBuilder
|
||||
# gebauten Binaries direkt hochlaedt. Dieser Workflow baut nur das Docker-Image.
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -18,3 +18,7 @@ data/
|
||||
|
||||
!data/orca_filaments.json
|
||||
.runner-token
|
||||
|
||||
# Dev-only Dateien — nicht ins öffentliche Repo
|
||||
CLAUDE.md
|
||||
release.sh
|
||||
|
||||
33
CHANGES.md
Normal file
33
CHANGES.md
Normal file
@@ -0,0 +1,33 @@
|
||||
## KX-Bridge 0.9.27-nightly9 — Nightly Build
|
||||
|
||||
[experimentell] Ungetestete Features, nur für Tester geeignet.
|
||||
|
||||
### Änderungen seit `v0.9.26`
|
||||
|
||||
- fix(spoolman): Status-Dot beim Seitenload initialisieren
|
||||
- chore: CHANGES.md mit echtem Changelog aus Dev-Repo ins Release-Repo schreiben
|
||||
- fix(spoolman): SPOOLMAN_* env-Cache bei Restart leeren, Status-Dot nach Save aktualisieren
|
||||
- chore: README.es.md + CONTRIBUTING.md in release.sh-Sync aufnehmen
|
||||
- docs: Nightly-Sektion, Wartungshinweis + CONTRIBUTING.md, FR/IT-Sprachen, Downloads-Badge
|
||||
- fix(update): Nightly-Vergleich auf Versions-String umstellen (statt Datum)
|
||||
- feat(update): Nightly-Track vom Stable-Track trennen
|
||||
- fix(release): nightly immer auf nightly-Branch pushen, kein master-Push
|
||||
- fix(camera): exponentielles Backoff bei ffmpeg-Fehler + /api/camera/reset + ↺-Button
|
||||
- fix(release): Nightly-Release vom nightly-Branch erlauben
|
||||
- feat(i18n): fehlende UI-Übersetzungen ergänzt + Keys alphabetisch sortiert (PR #70 @fenopy)
|
||||
- fix: config/config.ini.example beim Release-Sync mitübertragen (Issue #72)
|
||||
- feat(ui): Integrationen-Tab in Settings (Spoolman + Obico-Hinweis)
|
||||
- feat(stack): KobraX Full Stack Compose für Portainer (KX-Bridge + Obico + Spoolman)
|
||||
- feat(release): Nightly/Stable Release-Workflow mit eigenem Docker-Tag
|
||||
- feat(spoolman): optionale Spoolman-Filamentverbrauch-Integration (PR #65, @p2l)
|
||||
- fix(release): Artifact-Download per HTTP statt lokalem Dateipfad
|
||||
|
||||
---
|
||||
|
||||
### Docker-Image aktualisieren
|
||||
|
||||
```bash
|
||||
docker compose pull && docker compose up -d
|
||||
```
|
||||
|
||||
Image-Tag: `gitea.it-drui.de/viewit/kx-bridge:nightly`
|
||||
147
README.dev.md
Normal file
147
README.dev.md
Normal file
@@ -0,0 +1,147 @@
|
||||
<p align="center"><img src="knlogo.png" alt="KX-Bridge Logo" width="180"/></p>
|
||||
|
||||
# KX-Bridge – Dev Branch
|
||||
|
||||
> **Achtung:** Dies ist der Entwicklungs-Branch. Builds hier sind experimentell und nicht für den produktiven Einsatz geeignet.
|
||||
> Für stabile Releases → [KX-Bridge-Release](https://gitea.it-drui.de/viewit/KX-Bridge-Release/releases)
|
||||
|
||||
---
|
||||
|
||||
## Versionsschema
|
||||
|
||||
Dev-Builds verwenden das Format:
|
||||
|
||||
```
|
||||
<basis-version>-dev+<git-hash>
|
||||
```
|
||||
|
||||
**Beispiel:** `0.9.1-dev+04a6a20`
|
||||
|
||||
- `0.9.1` – Basis der aktuellen stabilen Version
|
||||
- `-dev` – kennzeichnet den Entwicklungs-Branch
|
||||
- `+04a6a20` – 7-stelliger Git-Commit-Hash, eindeutig je Build
|
||||
|
||||
---
|
||||
|
||||
## Dev-Binaries testen
|
||||
|
||||
Dev-Releases sind auf Gitea als Pre-Releases verfügbar:
|
||||
[Dev-Releases](https://gitea.it-drui.de/viewit/KX-Bridge-Release/releases)
|
||||
|
||||
### Docker (empfohlen)
|
||||
|
||||
```bash
|
||||
git clone <repo-url> -b dev
|
||||
cd kobrax
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Linux-Binary
|
||||
|
||||
```bash
|
||||
# Dev-Release herunterladen (kx-bridge-linux.zip)
|
||||
unzip kx-bridge-linux.zip
|
||||
chmod +x kx-bridge
|
||||
./kx-bridge
|
||||
```
|
||||
|
||||
`config/config.ini` und `data/` (SQLite + GCode-Store) werden **neben dem Binary**
|
||||
angelegt. Beim Erststart ohne Drucker zeigt die UI auf `http://localhost:7125` den
|
||||
Drucker-Tab mit "+ Drucker hinzufügen" — dort nur die IP eingeben, der Rest wird
|
||||
automatisch importiert.
|
||||
|
||||
### Windows-EXE
|
||||
|
||||
```
|
||||
# Dev-Release herunterladen (kx-bridge-windows.zip)
|
||||
# kx-bridge.exe starten — config/ und data/ liegen daneben
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Update-Kanal
|
||||
|
||||
Dev-Versionen prüfen automatisch auf neue **Dev-Releases** — nicht auf stabile Releases.
|
||||
Im Settings-Modal → „Auf Updates prüfen" zeigt den neuesten Dev-Build an.
|
||||
|
||||
---
|
||||
|
||||
## Aktive Entwicklung (Stand 2026-05-10)
|
||||
|
||||
Stand `dev`-Branch über v0.9.7 hinaus:
|
||||
|
||||
| Feature | Status |
|
||||
|---------|--------|
|
||||
| MMU-Emulation (`/printer/objects/query?mmu`) für OrcaSlicer Filament-Sync | ✅ |
|
||||
| GCode Store (SQLite + Thumbnails) | ✅ |
|
||||
| Browser-Tab mit Suche/Filter/Sortierung | ✅ |
|
||||
| Filament-Dialog: Per-Kanal-Remapping (GCode-Kanal → AMS-Slot) | ✅ |
|
||||
| MQTT Print-Payload `ams_settings.ams_box_mapping` (nested) | ✅ |
|
||||
| Print-History in SQLite | ✅ |
|
||||
| Multi-Printer Support (Drucker-Tab + Header-Dropdown) | ✅ |
|
||||
| **Multi-Printer in einer Bridge-Instanz** (ein Prozess, N Listener) | ✅ |
|
||||
| Drucker-Emulator (`_archive/tools/kx_printer_emulator.py`) | ✅ |
|
||||
| i18n DE/EN für alle neuen UI-Elemente | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## Multi-Printer-Setup
|
||||
|
||||
Eine Bridge-Instanz kann jetzt mehrere Drucker gleichzeitig verwalten — ein Prozess,
|
||||
N MQTT-Verbindungen, N HTTP-Listener, geteilte SQLite + GCode-Verzeichnis.
|
||||
|
||||
### Konfiguration
|
||||
|
||||
In `config/config.ini` pro Drucker eine `[printer_N]`-Sektion anlegen:
|
||||
|
||||
```ini
|
||||
[printer_1]
|
||||
name = Kobra X
|
||||
printer_ip = <DRUCKER_IP_1>
|
||||
mqtt_port = 9883
|
||||
username = <MQTT_USER>
|
||||
password = <MQTT_PASSWORT>
|
||||
mode_id = 20030
|
||||
device_id = <DEVICE_ID_1>
|
||||
http_port = 7125
|
||||
|
||||
[printer_2]
|
||||
name = Drucker 2
|
||||
printer_ip = <DRUCKER_IP_2>
|
||||
mqtt_port = 9883
|
||||
username = <MQTT_USER>
|
||||
password = <MQTT_PASSWORT>
|
||||
mode_id = 20030
|
||||
device_id = <DEVICE_ID_2>
|
||||
http_port = 7126
|
||||
```
|
||||
|
||||
Credentials per `extract_credentials` oder `fetch_credentials` ermitteln (siehe Haupt-README).
|
||||
|
||||
`http_port` ist optional — Default ist `7125 + (N-1)`. Wenn keine `[printer_N]`-Sektionen
|
||||
existieren, läuft die Bridge im klassischen Einzel-Modus mit `[connection]` und einem Listener.
|
||||
|
||||
### Docker
|
||||
|
||||
`docker-compose.yml` exposed jetzt einen Port-Range `7125-7130`:
|
||||
|
||||
```yaml
|
||||
ports:
|
||||
- "7125-7130:7125-7130"
|
||||
```
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
# Drucker 1: http://localhost:7125
|
||||
# Drucker 2: http://localhost:7126
|
||||
```
|
||||
|
||||
OrcaSlicer / Mainsail richten den Klipper-Endpunkt pro Drucker auf den jeweiligen Port —
|
||||
keine Slicer-Anpassungen nötig.
|
||||
|
||||
---
|
||||
|
||||
## Stabile Version
|
||||
|
||||
Für den produktiven Einsatz bitte die stabile Version verwenden:
|
||||
[→ Zum stabilen Release](https://gitea.it-drui.de/viewit/KX-Bridge-Release/releases)
|
||||
3
pytest.ini
Normal file
3
pytest.ini
Normal file
@@ -0,0 +1,3 @@
|
||||
[pytest]
|
||||
asyncio_mode = auto
|
||||
testpaths = tests
|
||||
11
releases/0.9.27/SHA256SUMS.txt
Normal file
11
releases/0.9.27/SHA256SUMS.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
06873a3b6773e6e755deff33dba468dee3af09859f9b026b14a600501c8285cb anycubic-certs.zip
|
||||
68e08c6b6badb2bf86f61e2164e96b902944c885f083a598ea4e3c854c432e91 extract_credentials
|
||||
8d4d78bdc887e2512790805b711b941420536d5f0f30043b5f3bc74d4fa893d3 extract_credentials.exe
|
||||
9b79a5f8edc734018fc547ac232ddd822ec5fee050e99e3305ccf8f38b177c9e fetch_credentials
|
||||
b79615bc2f9df33bccd5471bfcd83c9bdc5291e857fe5b04927b171342bc1b48 fetch_credentials.exe
|
||||
37ae8e3f4dc7bb6cf434de980db4aed9c1047d995063ce289bdc268f7764380e kx-bridge.exe
|
||||
4f636f91fef7eb1ea1ad1ae8c7f7eaa64b725e4dc2e74db42a53ce5dc5808ba3 kx-bridge-linux-amd64
|
||||
b0ff6fa222cfbf79e0ab609aac4c9d3b1acd80b5c4df10c7847e0c7d125913bc kx-bridge-linux-amd64.zip
|
||||
0cd9448ceec03cc7f545f9c62a21b7075a866dba5ee396ec26b48816f927db1a kx-bridge-linux-arm64
|
||||
99c4641bbdcc000b2cf2142ee01c16942b13da47ea837885fa1be68e984f6101 kx-bridge-linux-arm64.zip
|
||||
31659f76913e1c785cfa9e0a9e87f893a483a6a55248006b046ac07b25b40870 kx-bridge-windows.zip
|
||||
BIN
releases/0.9.27/anycubic-certs.zip
Normal file
BIN
releases/0.9.27/anycubic-certs.zip
Normal file
Binary file not shown.
24
releases/0.9.27/anycubic_slicer.crt
Normal file
24
releases/0.9.27/anycubic_slicer.crt
Normal file
@@ -0,0 +1,24 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEDTCCAvWgAwIBAgICAZAwDQYJKoZIhvcNAQEFBQAwgZsxCzAJBgNVBAYTAkNO
|
||||
MRIwEAYDVQQIDAlHdWFuZ2RvbmcxETAPBgNVBAcMCFNoZW56aGVuMREwDwYDVQQK
|
||||
DAhBbnljdWJpYzERMA8GA1UECwwIQW55Y3ViaWMxEzARBgNVBAMMCkFDIFJvb3Qg
|
||||
Q0ExKjAoBgkqhkiG9w0BCQEWG2FueWN1YmljX2Nsb3VkQGFueWN1YmljLmNvbTAg
|
||||
Fw0yMzA3MjAwMzI3NTFaGA8yMTIzMDcyMTAzMjc1MVowgZ8xCzAJBgNVBAYTAkNO
|
||||
MRIwEAYDVQQIDAlHdWFuZ2RvbmcxETAPBgNVBAcMCFNoZW56aGVuMREwDwYDVQQK
|
||||
DAhBbnljdWJpYzERMA8GA1UECwwIQW55Y3ViaWMxFzAVBgNVBAMMDkFueWN1Ymlj
|
||||
U2xpY2VyMSowKAYJKoZIhvcNAQkBFhthbnljdWJpY19jbG91ZEBhbnljdWJpYy5j
|
||||
b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDdoQ7g2F/yecfpdlqT
|
||||
b8W/84r3vQ4ZEWx2PbSTBcGD55HmzJp2lwABHFHbn4CltT9YzoJWpOiVMHYnyPep
|
||||
43tkNUIcGm7z0jrTD5djyYjVAzEitkNzJspKK/xcVmZe/V7Q3IAWXtzgWCd0YpVk
|
||||
K3J0HqoqJvcTSnYe4VXxbIGwbpeYyji9W/DuG1M4Z+sFiPDWeR9xo5IXRU5ZwaTP
|
||||
8OiCCLSBbeKgf0UFWTIZdJ1JXJ7efbbstZOjf5L9LhBIC0hLdL4jlMpF7r0ThecJ
|
||||
cTx9Bnw/hhy+i32rJTRzZDIaLhKg/bka9ZrORZdxxQRiPoMjLjoxtr4+AUaeLWkI
|
||||
ajSJAgMBAAGjUzBRMB0GA1UdDgQWBBRI4P3/uKdYYFPEcFIwYxdv1p9gETAfBgNV
|
||||
HSMEGDAWgBQlkDqpFERfr3u1rR9gNbNKtgrHIjAPBgNVHRMBAf8EBTADAQH/MA0G
|
||||
CSqGSIb3DQEBBQUAA4IBAQBP3ws80Y9eBR2lpjYP3rVvH8kA6+LnEXT4PpHj+fSw
|
||||
jciaNskzpiwNvBy00m32ACR5YKlMUjevlQuyyw+LQbTUwAEOwyy9SDQpiXdjL6q3
|
||||
SPQ4aB4A57nFXOGrthc/nb9yFcteWrZrKbwvVUu2vqU7U8n7lJKjhVuFRWSXS3SV
|
||||
sPc9JZ21kpPYWKbGtfD6jUlW0Ip+PurLw9FrbVwnEcOMf/ezSlrH5c8mfJyo8pVk
|
||||
aC/6PpReqijusOSRZ5oLyhPvtgddXseJFByun1Ud0CDlFA05nGGPmnVcXD+GMnHH
|
||||
i6baCTeifwp5Jpdzv4imcCPvayKUNuX32vYNfNkWC/R5
|
||||
-----END CERTIFICATE-----
|
||||
28
releases/0.9.27/anycubic_slicer.key
Normal file
28
releases/0.9.27/anycubic_slicer.key
Normal file
@@ -0,0 +1,28 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDdoQ7g2F/yecfp
|
||||
dlqTb8W/84r3vQ4ZEWx2PbSTBcGD55HmzJp2lwABHFHbn4CltT9YzoJWpOiVMHYn
|
||||
yPep43tkNUIcGm7z0jrTD5djyYjVAzEitkNzJspKK/xcVmZe/V7Q3IAWXtzgWCd0
|
||||
YpVkK3J0HqoqJvcTSnYe4VXxbIGwbpeYyji9W/DuG1M4Z+sFiPDWeR9xo5IXRU5Z
|
||||
waTP8OiCCLSBbeKgf0UFWTIZdJ1JXJ7efbbstZOjf5L9LhBIC0hLdL4jlMpF7r0T
|
||||
hecJcTx9Bnw/hhy+i32rJTRzZDIaLhKg/bka9ZrORZdxxQRiPoMjLjoxtr4+AUae
|
||||
LWkIajSJAgMBAAECggEASwRkC9lRiLqN30kvWW5g6hsec8KrTfLm2pMCVy2AlgxB
|
||||
B3VD51YvKzERyBwSKITT/1RPK9K/4xe3NrpAkmGsd3vLd8W+vorvXFePr7gct7VP
|
||||
4Wb+J7D+keKXlg2sswRiHqI0PN45Nzq/iBaCaJiIMiPbB0+PHBl9J/Cv7XsD3tq+
|
||||
9WKhvXf2g1g9GMrLaCCcWXWCqcu0LlbqJnw3yMnJLSltmyFTmlVLjDHM75bMVz97
|
||||
4emQzOlnRN2yA5cWWCaM+mgjNM2aWwUsXBZzCgwSqSaj1QD4B/epCuDBORWHS9D6
|
||||
jL15w8xjly9q8OS+4d6beR5h9GiPyMK4Ff2wXImCXQKBgQDwXxtrL+kVZrQ/qftj
|
||||
24F3+QDN0j5Z3lUMTfZPn6ng/E/aBfn8KcWJHj2vYkKZdB5wOXJr56BYe3Hukzfp
|
||||
QF0E2+g1WAGskF1mb/vVab54geox5Y6CA+ionRn2kcCwybVkktR/0JK2UV9Qjb/z
|
||||
k1WU+RUhNrW/GDBqYulaadnR+wKBgQDsCf2/yKGPxj4pIvAtn5RFSlfscddgkSnc
|
||||
ouBkDXEp5ta+5PGrlrdzS/F0vFhvBPbfbVJxVwRnM/Oqj8c0/bj7oc5RpPxirciO
|
||||
AaovKVPTiORaviytnB2HgkflkJfy5vdXv4ZQahAV/UwtSmLwBshe+Ya68MAFrQRa
|
||||
7M4z6k4QSwKBgQCm7OVVoofzXMeADsONrTpT3pA4XvD95/CYAuwyj2ah35Z0igH4
|
||||
o+mSN3YO/eXSO1mIBdz4Inqv98o/K+2ABjqSzUSNBvjipb63DL2Oj0i+1zmUPR6i
|
||||
G6TOs4r8OGvgWbOmjHEV8fpwskHG5ymONZsRQYjy79N3SY0V1GrJZwjlUQKBgD0x
|
||||
AeWcP7YkMK09b4KEYk3sTgrwIGPafj3Cw+VsTrAMNhPbCoPvWLO9NmWLBmoRoWae
|
||||
0sarRmry3vKSv5QPSsuBURl9aiiy4NFfwRzk2+R1Eq4rqy1+0XD152muKJZCJlFL
|
||||
R6jFNlJdDkiXhjqvp3ZnvfPswfs2tXBU/8gZsA8tAoGBALXfc5m9I5R1l1zN7tpa
|
||||
ncA0S3EKzqmuCc3KzlS6OS0e9Lz1MsmfEsvxvW3w4SrdfTbwQpEy9RNg89dlgPtc
|
||||
rdId1QdN2eWPY5M4lz9n9EYdzi9ufoKAEYu2a0lP+qz690JwmL1Jx49bvQEn5Nu0
|
||||
4swn72uwBRlhjAw46MF77SBQ
|
||||
-----END PRIVATE KEY-----
|
||||
89
releases/0.9.27/build_exe.log
Normal file
89
releases/0.9.27/build_exe.log
Normal file
@@ -0,0 +1,89 @@
|
||||
pyinstaller --onefile --name extract_credentials /src/extract_credentials.py && cp /src/dist/extract_credentials.exe /out/ && pyinstaller --onefile --name fetch_credentials /src/fetch_credentials.py && cp /src/dist/fetch_credentials.exe /out/
|
||||
114 INFO: PyInstaller: 3.6
|
||||
114 INFO: Python: 3.7.5
|
||||
114 INFO: Platform: Windows-7-6.1.7601-SP1
|
||||
115 INFO: wrote Z:\src\extract_credentials.spec
|
||||
120 INFO: UPX is not available.
|
||||
121 INFO: Extending PYTHONPATH with paths
|
||||
['Z:\\src', 'Z:\\src']
|
||||
121 INFO: checking Analysis
|
||||
121 INFO: Building Analysis because Analysis-00.toc is non existent
|
||||
121 INFO: Initializing module dependency graph...
|
||||
124 INFO: Caching module graph hooks...
|
||||
130 INFO: Analyzing base_library.zip ...
|
||||
2142 INFO: Caching module dependency graph...
|
||||
2226 INFO: running Analysis Analysis-00.toc
|
||||
2234 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable
|
||||
required by c:\Python37\python.exe
|
||||
2467 INFO: Analyzing \src\extract_credentials.py
|
||||
2497 INFO: Processing module hooks...
|
||||
2497 INFO: Loading module hook "hook-encodings.py"...
|
||||
2649 INFO: Loading module hook "hook-pydoc.py"...
|
||||
2650 INFO: Loading module hook "hook-xml.py"...
|
||||
2788 INFO: Looking for ctypes DLLs
|
||||
2791 INFO: Analyzing run-time hooks ...
|
||||
2794 INFO: Looking for dynamic libraries
|
||||
2909 INFO: Looking for eggs
|
||||
2909 INFO: Using Python library c:\Python37\python37.dll
|
||||
2909 INFO: Found binding redirects:
|
||||
[]
|
||||
2910 INFO: Warnings written to Z:\src\build\extract_credentials\warn-extract_credentials.txt
|
||||
2927 INFO: Graph cross-reference written to Z:\src\build\extract_credentials\xref-extract_credentials.html
|
||||
2939 INFO: checking PYZ
|
||||
2939 INFO: Building PYZ because PYZ-00.toc is non existent
|
||||
2939 INFO: Building PYZ (ZlibArchive) Z:\src\build\extract_credentials\PYZ-00.pyz
|
||||
3199 INFO: Building PYZ (ZlibArchive) Z:\src\build\extract_credentials\PYZ-00.pyz completed successfully.
|
||||
3203 INFO: checking PKG
|
||||
3203 INFO: Building PKG because PKG-00.toc is non existent
|
||||
3203 INFO: Building PKG (CArchive) PKG-00.pkg
|
||||
4599 INFO: Building PKG (CArchive) PKG-00.pkg completed successfully.
|
||||
4601 INFO: Bootloader c:\Python37\lib\site-packages\PyInstaller\bootloader\Windows-64bit\run.exe
|
||||
4601 INFO: checking EXE
|
||||
4601 INFO: Building EXE because EXE-00.toc is non existent
|
||||
4601 INFO: Building EXE from EXE-00.toc
|
||||
4601 INFO: Appending archive to EXE Z:\src\dist\extract_credentials.exe
|
||||
4604 INFO: Building EXE from EXE-00.toc completed successfully.
|
||||
77 INFO: PyInstaller: 3.6
|
||||
77 INFO: Python: 3.7.5
|
||||
77 INFO: Platform: Windows-7-6.1.7601-SP1
|
||||
77 INFO: wrote Z:\src\fetch_credentials.spec
|
||||
83 INFO: UPX is not available.
|
||||
84 INFO: Extending PYTHONPATH with paths
|
||||
['Z:\\src', 'Z:\\src']
|
||||
84 INFO: checking Analysis
|
||||
84 INFO: Building Analysis because Analysis-00.toc is non existent
|
||||
84 INFO: Initializing module dependency graph...
|
||||
88 INFO: Caching module graph hooks...
|
||||
94 INFO: Analyzing base_library.zip ...
|
||||
2079 INFO: Caching module dependency graph...
|
||||
2168 INFO: running Analysis Analysis-00.toc
|
||||
2170 INFO: Adding Microsoft.Windows.Common-Controls to dependent assemblies of final executable
|
||||
required by c:\Python37\python.exe
|
||||
2425 INFO: Analyzing \src\fetch_credentials.py
|
||||
2501 INFO: Processing module hooks...
|
||||
2501 INFO: Loading module hook "hook-encodings.py"...
|
||||
2630 INFO: Loading module hook "hook-pydoc.py"...
|
||||
2631 INFO: Loading module hook "hook-xml.py"...
|
||||
2765 INFO: Looking for ctypes DLLs
|
||||
2765 INFO: Analyzing run-time hooks ...
|
||||
2768 INFO: Looking for dynamic libraries
|
||||
2878 INFO: Looking for eggs
|
||||
2878 INFO: Using Python library c:\Python37\python37.dll
|
||||
2878 INFO: Found binding redirects:
|
||||
[]
|
||||
2880 INFO: Warnings written to Z:\src\build\fetch_credentials\warn-fetch_credentials.txt
|
||||
2896 INFO: Graph cross-reference written to Z:\src\build\fetch_credentials\xref-fetch_credentials.html
|
||||
2901 INFO: checking PYZ
|
||||
2901 INFO: Building PYZ because PYZ-00.toc is non existent
|
||||
2901 INFO: Building PYZ (ZlibArchive) Z:\src\build\fetch_credentials\PYZ-00.pyz
|
||||
3159 INFO: Building PYZ (ZlibArchive) Z:\src\build\fetch_credentials\PYZ-00.pyz completed successfully.
|
||||
3163 INFO: checking PKG
|
||||
3163 INFO: Building PKG because PKG-00.toc is non existent
|
||||
3163 INFO: Building PKG (CArchive) PKG-00.pkg
|
||||
4428 INFO: Building PKG (CArchive) PKG-00.pkg completed successfully.
|
||||
4430 INFO: Bootloader c:\Python37\lib\site-packages\PyInstaller\bootloader\Windows-64bit\run.exe
|
||||
4430 INFO: checking EXE
|
||||
4430 INFO: Building EXE because EXE-00.toc is non existent
|
||||
4430 INFO: Building EXE from EXE-00.toc
|
||||
4430 INFO: Appending archive to EXE Z:\src\dist\fetch_credentials.exe
|
||||
4434 INFO: Building EXE from EXE-00.toc completed successfully.
|
||||
56
releases/0.9.27/build_extract.log
Normal file
56
releases/0.9.27/build_extract.log
Normal file
@@ -0,0 +1,56 @@
|
||||
32 INFO: PyInstaller: 6.19.0, contrib hooks: 2026.4
|
||||
32 INFO: Python: 3.12.3
|
||||
33 INFO: Platform: Linux-6.17.0-35-generic-x86_64-with-glibc2.39
|
||||
33 INFO: Python environment: /usr
|
||||
33 INFO: wrote /home/coding/Source/KX-Bridge-Release/build/extract_credentials.spec
|
||||
34 INFO: Module search paths (PYTHONPATH):
|
||||
['/usr/lib/python312.zip',
|
||||
'/usr/lib/python3.12',
|
||||
'/usr/lib/python3.12/lib-dynload',
|
||||
'/home/coding/.local/lib/python3.12/site-packages',
|
||||
'/usr/local/lib/python3.12/dist-packages',
|
||||
'/usr/lib/python3/dist-packages',
|
||||
'/usr/lib/python3.12/dist-packages',
|
||||
'/home/coding/Source/KX-Bridge-Release']
|
||||
352 INFO: checking Analysis
|
||||
352 INFO: Building Analysis because Analysis-00.toc is non existent
|
||||
352 INFO: Looking for Python shared library...
|
||||
364 WARNING: Unrecognised line of output 'Der Cache wurde generiert von: ldconfig (Ubuntu GLIBC 2.39-0ubuntu8.7) stable release version 2.39' from ldconfig
|
||||
364 INFO: Using Python shared library: /lib/x86_64-linux-gnu/libpython3.12.so.1.0
|
||||
364 INFO: Running Analysis Analysis-00.toc
|
||||
364 INFO: Target bytecode optimization level: 0
|
||||
364 INFO: Initializing module dependency graph...
|
||||
366 INFO: Initializing module graph hook caches...
|
||||
380 INFO: Analyzing modules for base_library.zip ...
|
||||
1005 INFO: Processing standard module hook 'hook-encodings.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
1923 INFO: Processing standard module hook 'hook-pickle.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
2491 INFO: Processing standard module hook 'hook-heapq.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
2739 INFO: Caching module dependency graph...
|
||||
2764 INFO: Analyzing /home/coding/Source/KX-Bridge-Release/extract_credentials.py
|
||||
2790 INFO: Processing standard module hook 'hook-platform.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
2801 INFO: Processing standard module hook 'hook-_ctypes.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
2808 INFO: Processing module hooks (post-graph stage)...
|
||||
2812 INFO: Performing binary vs. data reclassification (1 entries)
|
||||
2818 INFO: Looking for ctypes DLLs
|
||||
2825 INFO: Analyzing run-time hooks ...
|
||||
2825 INFO: Including run-time hook 'pyi_rth_inspect.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks/rthooks'
|
||||
2829 INFO: Creating base_library.zip...
|
||||
2841 INFO: Looking for dynamic libraries
|
||||
2987 INFO: Warnings written to /home/coding/Source/KX-Bridge-Release/build/pyinstaller/extract_credentials/warn-extract_credentials.txt
|
||||
2993 INFO: Graph cross-reference written to /home/coding/Source/KX-Bridge-Release/build/pyinstaller/extract_credentials/xref-extract_credentials.html
|
||||
3000 INFO: checking PYZ
|
||||
3000 INFO: Building PYZ because PYZ-00.toc is non existent
|
||||
3000 INFO: Building PYZ (ZlibArchive) /home/coding/Source/KX-Bridge-Release/build/pyinstaller/extract_credentials/PYZ-00.pyz
|
||||
3099 INFO: Building PYZ (ZlibArchive) /home/coding/Source/KX-Bridge-Release/build/pyinstaller/extract_credentials/PYZ-00.pyz completed successfully.
|
||||
3105 INFO: checking PKG
|
||||
3105 INFO: Building PKG because PKG-00.toc is non existent
|
||||
3105 INFO: Building PKG (CArchive) extract_credentials.pkg
|
||||
5376 INFO: Building PKG (CArchive) extract_credentials.pkg completed successfully.
|
||||
5376 INFO: Bootloader /home/coding/.local/lib/python3.12/site-packages/PyInstaller/bootloader/Linux-64bit-intel/run
|
||||
5376 INFO: checking EXE
|
||||
5376 INFO: Building EXE because EXE-00.toc is non existent
|
||||
5376 INFO: Building EXE from EXE-00.toc
|
||||
5376 INFO: Copying bootloader EXE to /home/coding/Source/KX-Bridge-Release/releases/0.9.27/extract_credentials
|
||||
5376 INFO: Appending PKG archive to custom ELF section in EXE
|
||||
5386 INFO: Building EXE from EXE-00.toc completed successfully.
|
||||
5386 INFO: Build complete! The results are available in: /home/coding/Source/KX-Bridge-Release/releases/0.9.27
|
||||
91
releases/0.9.27/build_fetch.log
Normal file
91
releases/0.9.27/build_fetch.log
Normal file
@@ -0,0 +1,91 @@
|
||||
35 INFO: PyInstaller: 6.19.0, contrib hooks: 2026.4
|
||||
35 INFO: Python: 3.12.3
|
||||
36 INFO: Platform: Linux-6.17.0-35-generic-x86_64-with-glibc2.39
|
||||
36 INFO: Python environment: /usr
|
||||
36 INFO: wrote /home/coding/Source/KX-Bridge-Release/build/fetch_credentials.spec
|
||||
37 WARNING: collect_data_files - skipping data collection for module 'pycryptodome' as it is not a package.
|
||||
37 WARNING: collect_dynamic_libs - skipping library collection for module 'pycryptodome' as it is not a package.
|
||||
117 INFO: Module search paths (PYTHONPATH):
|
||||
['/usr/lib/python312.zip',
|
||||
'/usr/lib/python3.12',
|
||||
'/usr/lib/python3.12/lib-dynload',
|
||||
'/home/coding/.local/lib/python3.12/site-packages',
|
||||
'/usr/local/lib/python3.12/dist-packages',
|
||||
'/usr/lib/python3/dist-packages',
|
||||
'/usr/lib/python3.12/dist-packages',
|
||||
'/home/coding/Source/KX-Bridge-Release']
|
||||
458 INFO: checking Analysis
|
||||
458 INFO: Building Analysis because Analysis-00.toc is non existent
|
||||
458 INFO: Looking for Python shared library...
|
||||
475 WARNING: Unrecognised line of output 'Der Cache wurde generiert von: ldconfig (Ubuntu GLIBC 2.39-0ubuntu8.7) stable release version 2.39' from ldconfig
|
||||
475 INFO: Using Python shared library: /lib/x86_64-linux-gnu/libpython3.12.so.1.0
|
||||
475 INFO: Running Analysis Analysis-00.toc
|
||||
475 INFO: Target bytecode optimization level: 0
|
||||
476 INFO: Initializing module dependency graph...
|
||||
476 INFO: Initializing module graph hook caches...
|
||||
491 INFO: Analyzing modules for base_library.zip ...
|
||||
1017 INFO: Processing standard module hook 'hook-encodings.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
1871 INFO: Processing standard module hook 'hook-pickle.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
2469 INFO: Processing standard module hook 'hook-heapq.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
2692 INFO: Caching module dependency graph...
|
||||
2717 INFO: Analyzing /home/coding/Source/KX-Bridge-Release/fetch_credentials.py
|
||||
2750 INFO: Processing standard module hook 'hook-urllib3.py' from '/home/coding/.local/lib/python3.12/site-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
2817 INFO: Processing pre-safe-import-module hook 'hook-typing_extensions.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
2818 INFO: SetuptoolsInfo: initializing cached setuptools info...
|
||||
3154 INFO: Processing standard module hook 'hook-multiprocessing.util.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
3216 INFO: Processing standard module hook 'hook-xml.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
3402 INFO: Processing standard module hook 'hook-_ctypes.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
4175 INFO: Processing standard module hook 'hook-chardet.py' from '/home/coding/.local/lib/python3.12/site-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
4759 INFO: Processing standard module hook 'hook-cryptography.py' from '/home/coding/.local/lib/python3.12/site-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
5142 INFO: hook-cryptography: cryptography uses dynamically-linked OpenSSL: '/lib/x86_64-linux-gnu/libssl.so.3'
|
||||
5351 INFO: Processing standard module hook 'hook-bcrypt.py' from '/home/coding/.local/lib/python3.12/site-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
5426 INFO: Processing standard module hook 'hook-certifi.py' from '/home/coding/.local/lib/python3.12/site-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
5502 INFO: Processing standard module hook 'hook-Crypto.py' from '/home/coding/.local/lib/python3.12/site-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
5706 INFO: Processing standard module hook 'hook-pycparser.py' from '/home/coding/.local/lib/python3.12/site-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
5802 INFO: Processing standard module hook 'hook-setuptools.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
5806 INFO: Processing pre-safe-import-module hook 'hook-distutils.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
5861 INFO: Processing standard module hook 'hook-sysconfig.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
5896 INFO: Processing standard module hook 'hook-platform.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
5906 INFO: Processing standard module hook 'hook-_osx_support.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
6028 INFO: Processing pre-safe-import-module hook 'hook-importlib_metadata.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
6141 INFO: Processing pre-safe-import-module hook 'hook-packaging.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
6502 INFO: Processing standard module hook 'hook-pkg_resources.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
7089 INFO: Processing standard module hook 'hook-xml.dom.domreg.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
7323 INFO: Processing standard module hook 'hook-sqlite3.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
7648 INFO: Processing standard module hook 'hook-difflib.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
7995 INFO: Processing module hooks (post-graph stage)...
|
||||
7997 WARNING: Hidden import "pycparser.lextab" not found!
|
||||
7997 WARNING: Hidden import "pycparser.yacctab" not found!
|
||||
8231 INFO: Processing pre-safe-import-module hook 'hook-platformdirs.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks/pre_safe_import_module'
|
||||
8237 INFO: Processing standard module hook 'hook-platformdirs.py' from '/home/coding/.local/lib/python3.12/site-packages/_pyinstaller_hooks_contrib/stdhooks'
|
||||
8304 INFO: Processing standard module hook 'hook-setuptools._vendor.importlib_metadata.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
8391 INFO: Processing standard module hook 'hook-setuptools._vendor.jaraco.text.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks'
|
||||
8490 INFO: Performing binary vs. data reclassification (51 entries)
|
||||
8605 INFO: Looking for ctypes DLLs
|
||||
8618 INFO: Analyzing run-time hooks ...
|
||||
8620 INFO: Including run-time hook 'pyi_rth_inspect.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks/rthooks'
|
||||
8622 INFO: Including run-time hook 'pyi_rth_pkgutil.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks/rthooks'
|
||||
8623 INFO: Including run-time hook 'pyi_rth_multiprocessing.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks/rthooks'
|
||||
8625 INFO: Including run-time hook 'pyi_rth_setuptools.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks/rthooks'
|
||||
8626 INFO: Including run-time hook 'pyi_rth_pkgres.py' from '/home/coding/.local/lib/python3.12/site-packages/PyInstaller/hooks/rthooks'
|
||||
8628 INFO: Including run-time hook 'pyi_rth_cryptography_openssl.py' from '/home/coding/.local/lib/python3.12/site-packages/_pyinstaller_hooks_contrib/rthooks'
|
||||
8635 INFO: Creating base_library.zip...
|
||||
8664 INFO: Looking for dynamic libraries
|
||||
9293 INFO: Warnings written to /home/coding/Source/KX-Bridge-Release/build/pyinstaller/fetch_credentials/warn-fetch_credentials.txt
|
||||
9315 INFO: Graph cross-reference written to /home/coding/Source/KX-Bridge-Release/build/pyinstaller/fetch_credentials/xref-fetch_credentials.html
|
||||
9327 INFO: checking PYZ
|
||||
9327 INFO: Building PYZ because PYZ-00.toc is non existent
|
||||
9327 INFO: Building PYZ (ZlibArchive) /home/coding/Source/KX-Bridge-Release/build/pyinstaller/fetch_credentials/PYZ-00.pyz
|
||||
9755 INFO: Building PYZ (ZlibArchive) /home/coding/Source/KX-Bridge-Release/build/pyinstaller/fetch_credentials/PYZ-00.pyz completed successfully.
|
||||
9766 INFO: checking PKG
|
||||
9766 INFO: Building PKG because PKG-00.toc is non existent
|
||||
9766 INFO: Building PKG (CArchive) fetch_credentials.pkg
|
||||
14335 INFO: Building PKG (CArchive) fetch_credentials.pkg completed successfully.
|
||||
14336 INFO: Bootloader /home/coding/.local/lib/python3.12/site-packages/PyInstaller/bootloader/Linux-64bit-intel/run
|
||||
14336 INFO: checking EXE
|
||||
14336 INFO: Building EXE because EXE-00.toc is non existent
|
||||
14336 INFO: Building EXE from EXE-00.toc
|
||||
14336 INFO: Copying bootloader EXE to /home/coding/Source/KX-Bridge-Release/releases/0.9.27/fetch_credentials
|
||||
14336 INFO: Appending PKG archive to custom ELF section in EXE
|
||||
14360 INFO: Building EXE from EXE-00.toc completed successfully.
|
||||
14361 INFO: Build complete! The results are available in: /home/coding/Source/KX-Bridge-Release/releases/0.9.27
|
||||
BIN
releases/0.9.27/fetch_credentials
Executable file
BIN
releases/0.9.27/fetch_credentials
Executable file
Binary file not shown.
BIN
releases/0.9.27/fetch_credentials.exe
Executable file
BIN
releases/0.9.27/fetch_credentials.exe
Executable file
Binary file not shown.
BIN
releases/0.9.27/kx-bridge-linux-amd64
Executable file
BIN
releases/0.9.27/kx-bridge-linux-amd64
Executable file
Binary file not shown.
BIN
releases/0.9.27/kx-bridge-linux-amd64.zip
Normal file
BIN
releases/0.9.27/kx-bridge-linux-amd64.zip
Normal file
Binary file not shown.
BIN
releases/0.9.27/kx-bridge-linux-arm64
Executable file
BIN
releases/0.9.27/kx-bridge-linux-arm64
Executable file
Binary file not shown.
BIN
releases/0.9.27/kx-bridge-linux-arm64.zip
Normal file
BIN
releases/0.9.27/kx-bridge-linux-arm64.zip
Normal file
Binary file not shown.
BIN
releases/0.9.27/kx-bridge-windows.zip
Normal file
BIN
releases/0.9.27/kx-bridge-windows.zip
Normal file
Binary file not shown.
BIN
releases/0.9.27/kx-bridge.exe
Executable file
BIN
releases/0.9.27/kx-bridge.exe
Executable file
Binary file not shown.
68
tests/conftest.py
Normal file
68
tests/conftest.py
Normal file
@@ -0,0 +1,68 @@
|
||||
"""
|
||||
Shared fixtures für KX-Bridge Tests.
|
||||
Startet die Bridge in-process mit einem Mock-MQTT-Client (kein Drucker nötig).
|
||||
"""
|
||||
import sys, types, argparse, pytest, pytest_asyncio
|
||||
from unittest.mock import MagicMock
|
||||
from aiohttp.test_utils import TestClient, TestServer
|
||||
|
||||
# ── Pfad ──────────────────────────────────────────────────────────────────────
|
||||
sys.path.insert(0, str(__import__("pathlib").Path(__file__).parent.parent / "bridge"))
|
||||
|
||||
# ── env_loader mocken (keine .env nötig) ──────────────────────────────────────
|
||||
env_mod = types.ModuleType("env_loader")
|
||||
env_mod.PRINTER_IP = ""
|
||||
env_mod.MQTT_PORT = 9883
|
||||
env_mod.USERNAME = ""
|
||||
env_mod.PASSWORD = ""
|
||||
env_mod.MODE_ID = "20030"
|
||||
env_mod.DEVICE_ID = ""
|
||||
sys.modules["env_loader"] = env_mod
|
||||
|
||||
# ── Bridge + App importieren ───────────────────────────────────────────────────
|
||||
from kobrax_moonraker_bridge import KobraXBridge, build_app # noqa: E402
|
||||
|
||||
|
||||
def make_mock_client():
|
||||
"""Minimaler Mock-MQTT-Client — keine Verbindung, keine Threads."""
|
||||
c = MagicMock()
|
||||
c.callbacks = {}
|
||||
c.connected = False
|
||||
return c
|
||||
|
||||
|
||||
def make_args(**overrides):
|
||||
args = argparse.Namespace(
|
||||
printer_ip = "",
|
||||
mqtt_port = 9883,
|
||||
username = "",
|
||||
password = "",
|
||||
mode_id = "20030",
|
||||
device_id = "",
|
||||
host = "127.0.0.1",
|
||||
port = 7125,
|
||||
)
|
||||
for k, v in overrides.items():
|
||||
setattr(args, k, v)
|
||||
return args
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
async def client():
|
||||
"""TestClient mit frischer Bridge-Instanz, ohne MQTT-Verbindung."""
|
||||
mock_client = make_mock_client()
|
||||
bridge = KobraXBridge(mock_client, args=make_args())
|
||||
app = build_app(bridge)
|
||||
async with TestClient(TestServer(app)) as c:
|
||||
yield c, bridge
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
async def client_configured():
|
||||
"""TestClient mit bereits konfigurierten Zugangsdaten."""
|
||||
mock_client = make_mock_client()
|
||||
args = make_args(printer_ip="192.168.1.100", device_id="abc123deadbeef")
|
||||
bridge = KobraXBridge(mock_client, args=args)
|
||||
app = build_app(bridge)
|
||||
async with TestClient(TestServer(app)) as c:
|
||||
yield c, bridge
|
||||
3
tests/requirements-test.txt
Normal file
3
tests/requirements-test.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
pytest
|
||||
pytest-asyncio
|
||||
aiohttp
|
||||
113
tests/test_api_state.py
Normal file
113
tests/test_api_state.py
Normal file
@@ -0,0 +1,113 @@
|
||||
"""
|
||||
Tests für /api/state — Drucker-Zustandsabfrage.
|
||||
"""
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_state_returns_200(client):
|
||||
c, _ = client
|
||||
resp = await c.get("/api/state")
|
||||
assert resp.status == 200
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_state_schema(client):
|
||||
"""Alle erwarteten Felder müssen vorhanden und typsicher sein."""
|
||||
c, _ = client
|
||||
resp = await c.get("/api/state")
|
||||
data = await resp.json()
|
||||
|
||||
assert isinstance(data["print_state"], str)
|
||||
assert isinstance(data["kobra_state"], str)
|
||||
assert isinstance(data["nozzle_temp"], float)
|
||||
assert isinstance(data["nozzle_target"], float)
|
||||
assert isinstance(data["bed_temp"], float)
|
||||
assert isinstance(data["bed_target"], float)
|
||||
assert isinstance(data["progress"], float)
|
||||
assert isinstance(data["print_duration"], int)
|
||||
assert isinstance(data["remain_time"], int)
|
||||
assert isinstance(data["curr_layer"], int)
|
||||
assert isinstance(data["total_layers"], int)
|
||||
assert isinstance(data["filename"], str)
|
||||
assert isinstance(data["fan_speed"], int)
|
||||
assert isinstance(data["light_on"], bool)
|
||||
assert isinstance(data["ams_slots"], list)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_state_initial_values(client):
|
||||
"""Im Offline-Start müssen Temperaturen 0 und Zustand 'standby' sein."""
|
||||
c, _ = client
|
||||
data = await (await c.get("/api/state")).json()
|
||||
|
||||
assert data["print_state"] == "standby"
|
||||
assert data["nozzle_temp"] == 0.0
|
||||
assert data["bed_temp"] == 0.0
|
||||
assert data["progress"] == 0.0
|
||||
assert data["filename"] == ""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_state_updates_after_mqtt_print_report(client):
|
||||
"""Simuliert ein eingehendes print/report MQTT-Paket und prüft State-Update."""
|
||||
c, bridge = client
|
||||
|
||||
# Simuliere MQTT-Nachricht wie vom echten Drucker
|
||||
bridge._on_print({
|
||||
"state": "printing",
|
||||
"data": {
|
||||
"filename": "test.gcode",
|
||||
"progress": 42,
|
||||
"print_time": 10, # Minuten → 600s
|
||||
"remain_time": 5, # Minuten → 300s
|
||||
"curr_layer": 20,
|
||||
"total_layers": 100,
|
||||
}
|
||||
})
|
||||
|
||||
data = await (await c.get("/api/state")).json()
|
||||
|
||||
assert data["print_state"] == "printing"
|
||||
assert data["filename"] == "test.gcode"
|
||||
assert data["progress"] == pytest.approx(0.42)
|
||||
assert data["print_duration"] == 600
|
||||
assert data["remain_time"] == 300
|
||||
assert data["curr_layer"] == 20
|
||||
assert data["total_layers"] == 100
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_state_updates_after_mqtt_temp_report(client):
|
||||
"""Simuliert ein tempature/report Paket."""
|
||||
c, bridge = client
|
||||
|
||||
bridge._on_temp({
|
||||
"data": {
|
||||
"curr_nozzle_temp": 215.3,
|
||||
"target_nozzle_temp": 220.0,
|
||||
"curr_hotbed_temp": 59.8,
|
||||
"target_hotbed_temp": 60.0,
|
||||
}
|
||||
})
|
||||
|
||||
data = await (await c.get("/api/state")).json()
|
||||
assert data["nozzle_temp"] == pytest.approx(215.3)
|
||||
assert data["nozzle_target"] == pytest.approx(220.0)
|
||||
assert data["bed_temp"] == pytest.approx(59.8)
|
||||
assert data["bed_target"] == pytest.approx(60.0)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_state_resets_on_cancel(client):
|
||||
"""Nach 'stoped' müssen Progress und Filename zurückgesetzt werden."""
|
||||
c, bridge = client
|
||||
|
||||
# Erst Druck simulieren
|
||||
bridge._on_print({"state": "printing", "data": {"filename": "x.gcode", "progress": 50}})
|
||||
# Dann Abbruch
|
||||
bridge._on_print({"state": "stoped", "data": {}})
|
||||
|
||||
data = await (await c.get("/api/state")).json()
|
||||
assert data["progress"] == 0.0
|
||||
assert data["filename"] == ""
|
||||
109
tests/test_install.sh
Normal file
109
tests/test_install.sh
Normal file
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env bash
|
||||
# test_install.sh – Smoke-Test: Release-Repo klonen, start.sh ausführen, HTTP prüfen.
|
||||
#
|
||||
# Simuliert den Weg eines anonymen Nutzers:
|
||||
# 1. Release-Repo klonen
|
||||
# 2. start.sh ausführen (baut Docker-Image, startet Container)
|
||||
# 3. HTTP-Endpunkte prüfen
|
||||
# 4. Aufräumen
|
||||
#
|
||||
# Voraussetzung: Docker installiert, Port 7125 frei
|
||||
#
|
||||
# Verwendung:
|
||||
# bash tests/test_install.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
GITEA_URL="https://gitea.it-drui.de/viewit/KX-Bridge-Release"
|
||||
WORK_DIR=$(mktemp -d /tmp/kx-bridge-test-XXXXXX)
|
||||
PASS=0; FAIL=0
|
||||
|
||||
ok() { echo " ✓ $*"; PASS=$((PASS+1)); }
|
||||
fail() { echo " ✗ $*"; FAIL=$((FAIL+1)); }
|
||||
|
||||
cleanup() {
|
||||
echo ""
|
||||
echo "[cleanup] Stoppe Container und lösche Testverzeichnis ..."
|
||||
cd "$WORK_DIR/KX-Bridge-Release" 2>/dev/null && docker-compose down 2>/dev/null || true
|
||||
rm -rf "$WORK_DIR"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
echo "=== KX-Bridge Installations-Smoke-Test ==="
|
||||
echo ""
|
||||
|
||||
# ── Schritt 1: Repo klonen ────────────────────────────────────────────────────
|
||||
echo "[1/5] Klone Release-Repo ..."
|
||||
git clone --depth=1 "$GITEA_URL" "$WORK_DIR/KX-Bridge-Release" > /dev/null 2>&1 \
|
||||
&& ok "Repo geklont" \
|
||||
|| { fail "git clone fehlgeschlagen"; exit 1; }
|
||||
|
||||
cd "$WORK_DIR/KX-Bridge-Release"
|
||||
|
||||
# ── Schritt 2: Erwartete Dateien vorhanden ────────────────────────────────────
|
||||
echo "[2/5] Prüfe Dateien im Repo ..."
|
||||
for f in start.sh docker-compose.yml Dockerfile kobrax_moonraker_bridge.py \
|
||||
anycubic_slicer.crt anycubic_slicer.key .env.example; do
|
||||
[[ -f "$f" ]] && ok "$f vorhanden" || fail "$f FEHLT"
|
||||
done
|
||||
|
||||
# Dockerfile darf keine 05_scripts/-Pfade enthalten
|
||||
if grep -q "05_scripts/" Dockerfile; then
|
||||
fail "Dockerfile enthält '05_scripts/' – falsches Dockerfile im Release-Repo!"
|
||||
else
|
||||
ok "Dockerfile Pfade korrekt (kein 05_scripts/-Präfix)"
|
||||
fi
|
||||
|
||||
# ── Schritt 3: start.sh ausführen ────────────────────────────────────────────
|
||||
echo "[3/5] Führe start.sh aus ..."
|
||||
chmod +x start.sh
|
||||
./start.sh > /tmp/kx-bridge-start.log 2>&1 \
|
||||
&& ok "start.sh erfolgreich" \
|
||||
|| { fail "start.sh fehlgeschlagen (siehe /tmp/kx-bridge-start.log)"; cat /tmp/kx-bridge-start.log; exit 1; }
|
||||
|
||||
# Kurz warten bis Bridge hochgefahren
|
||||
sleep 3
|
||||
|
||||
# ── Schritt 4: HTTP-Endpunkte prüfen ─────────────────────────────────────────
|
||||
echo "[4/5] Prüfe HTTP-Endpunkte ..."
|
||||
BASE="http://localhost:7125"
|
||||
|
||||
check_endpoint() {
|
||||
local path="$1"
|
||||
local desc="$2"
|
||||
local http_code
|
||||
http_code=$(curl -s -o /dev/null -w "%{http_code}" "$BASE$path")
|
||||
[[ "$http_code" == "200" ]] \
|
||||
&& ok "$desc ($path → $http_code)" \
|
||||
|| fail "$desc ($path → $http_code)"
|
||||
}
|
||||
|
||||
check_endpoint "/" "Web-UI (index.html)"
|
||||
check_endpoint "/api/state" "GET /api/state"
|
||||
check_endpoint "/api/settings" "GET /api/settings"
|
||||
check_endpoint "/server/info" "GET /server/info (Moonraker)"
|
||||
check_endpoint "/printer/info" "GET /printer/info (Moonraker)"
|
||||
check_endpoint "/printer/objects/list" "GET /printer/objects/list"
|
||||
check_endpoint "/api/version" "GET /api/version (OctoPrint compat)"
|
||||
|
||||
# Beim ersten Start: printer_ip muss leer sein → Settings-Modal würde sich öffnen
|
||||
SETTINGS=$(curl -s "$BASE/api/settings")
|
||||
PRINTER_IP=$(echo "$SETTINGS" | python3 -c "import sys,json; print(json.load(sys.stdin).get('printer_ip',''))" 2>/dev/null || echo "ERROR")
|
||||
[[ -z "$PRINTER_IP" ]] \
|
||||
&& ok "Erstkonfiguration erkannt: printer_ip leer → Settings-Modal öffnet sich" \
|
||||
|| fail "printer_ip sollte beim Erststart leer sein, ist: '$PRINTER_IP'"
|
||||
|
||||
# ── Schritt 5: Container läuft stabil ────────────────────────────────────────
|
||||
echo "[5/5] Prüfe Container-Stabilität ..."
|
||||
sleep 2
|
||||
RUNNING=$(docker-compose ps --services --filter "status=running" 2>/dev/null || true)
|
||||
[[ -n "$RUNNING" ]] \
|
||||
&& ok "Container läuft stabil" \
|
||||
|| fail "Container ist nicht mehr aktiv"
|
||||
|
||||
# ── Ergebnis ──────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "══════════════════════════════════════"
|
||||
echo " Ergebnis: $PASS bestanden, $FAIL fehlgeschlagen"
|
||||
echo "══════════════════════════════════════"
|
||||
[[ $FAIL -eq 0 ]] && exit 0 || exit 1
|
||||
77
tests/test_moonraker.py
Normal file
77
tests/test_moonraker.py
Normal file
@@ -0,0 +1,77 @@
|
||||
"""
|
||||
Tests für Moonraker-kompatible Endpunkte die OrcaSlicer aufruft.
|
||||
"""
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_server_info(client):
|
||||
c, _ = client
|
||||
resp = await c.get("/server/info")
|
||||
assert resp.status == 200
|
||||
data = await resp.json()
|
||||
assert data["result"]["klippy_state"] in ("ready", "standby", "error")
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_printer_info(client):
|
||||
c, _ = client
|
||||
resp = await c.get("/printer/info")
|
||||
assert resp.status == 200
|
||||
data = await resp.json()
|
||||
assert "hostname" in data["result"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_objects_list(client):
|
||||
c, _ = client
|
||||
resp = await c.get("/printer/objects/list")
|
||||
assert resp.status == 200
|
||||
data = await resp.json()
|
||||
objects = data["result"]["objects"]
|
||||
# OrcaSlicer erwartet mindestens diese Objekte
|
||||
for obj in ("print_stats", "heater_bed", "extruder", "display_status"):
|
||||
assert obj in objects
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_objects_query_print_stats(client):
|
||||
c, _ = client
|
||||
resp = await c.get("/printer/objects/query?print_stats")
|
||||
assert resp.status == 200
|
||||
data = await resp.json()
|
||||
ps = data["result"]["status"]["print_stats"]
|
||||
assert "state" in ps
|
||||
assert "filename" in ps
|
||||
assert "print_duration" in ps
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_objects_query_temperatures(client):
|
||||
c, _ = client
|
||||
resp = await c.get("/printer/objects/query?extruder&heater_bed")
|
||||
assert resp.status == 200
|
||||
data = await resp.json()
|
||||
status = data["result"]["status"]
|
||||
assert "temperature" in status["extruder"]
|
||||
assert "temperature" in status["heater_bed"]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_octoprint_version(client):
|
||||
"""OrcaSlicer probt /api/version um Drucker-Typ zu erkennen."""
|
||||
c, _ = client
|
||||
resp = await c.get("/api/version")
|
||||
assert resp.status == 200
|
||||
data = await resp.json()
|
||||
assert "server" in data
|
||||
assert "api" in data
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_files_list(client):
|
||||
c, _ = client
|
||||
resp = await c.get("/server/files/list")
|
||||
assert resp.status == 200
|
||||
data = await resp.json()
|
||||
assert isinstance(data["result"], list)
|
||||
82
tests/test_settings.py
Normal file
82
tests/test_settings.py
Normal file
@@ -0,0 +1,82 @@
|
||||
"""
|
||||
Tests für /api/settings — Lesen und Schreiben der Verbindungseinstellungen.
|
||||
"""
|
||||
import pytest
|
||||
import tempfile
|
||||
import pathlib
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_settings_get_returns_200(client):
|
||||
c, _ = client
|
||||
resp = await c.get("/api/settings")
|
||||
assert resp.status == 200
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_settings_get_schema(client):
|
||||
c, _ = client
|
||||
data = await (await c.get("/api/settings")).json()
|
||||
for key in ("printer_ip", "mqtt_port", "username", "password", "device_id", "mode_id"):
|
||||
assert key in data
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_settings_get_empty_when_unconfigured(client):
|
||||
"""Frische Bridge ohne Zugangsdaten → printer_ip und device_id leer."""
|
||||
c, _ = client
|
||||
data = await (await c.get("/api/settings")).json()
|
||||
assert data["printer_ip"] == ""
|
||||
assert data["device_id"] == ""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_settings_get_returns_configured_values(client_configured):
|
||||
"""Bridge mit Zugangsdaten → Werte korrekt zurückgegeben."""
|
||||
c, _ = client_configured
|
||||
data = await (await c.get("/api/settings")).json()
|
||||
assert data["printer_ip"] == "192.168.1.100"
|
||||
assert data["device_id"] == "abc123deadbeef"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_settings_post_writes_env(client):
|
||||
"""POST /api/settings schreibt Werte in .env-Datei."""
|
||||
c, bridge = client
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
env_path = pathlib.Path(tmpdir) / ".env"
|
||||
env_path.write_text("")
|
||||
bridge._find_env_path = lambda: env_path
|
||||
|
||||
resp = await c.post("/api/settings", json={
|
||||
"printer_ip": "10.0.0.5",
|
||||
"mqtt_port": 9883,
|
||||
"username": "userABCD",
|
||||
"password": "secret123",
|
||||
"device_id": "deadbeef01234567",
|
||||
"mode_id": "20030",
|
||||
})
|
||||
assert resp.status == 200
|
||||
|
||||
content = env_path.read_text()
|
||||
assert "PRINTER_IP=10.0.0.5" in content
|
||||
assert "MQTT_USERNAME=userABCD" in content
|
||||
assert "DEVICE_ID=deadbeef01234567" in content
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_settings_post_preserves_existing_keys(client):
|
||||
"""POST darf unbekannte Keys in .env nicht löschen (z.B. GITEA_TOKEN)."""
|
||||
c, bridge = client
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
env_path = pathlib.Path(tmpdir) / ".env"
|
||||
env_path.write_text("GITEA_TOKEN=mytoken\nPRINTER_IP=old\n")
|
||||
bridge._find_env_path = lambda: env_path
|
||||
|
||||
await c.post("/api/settings", json={"printer_ip": "10.0.0.99"})
|
||||
|
||||
content = env_path.read_text()
|
||||
assert "GITEA_TOKEN=mytoken" in content
|
||||
assert "PRINTER_IP=10.0.0.99" in content
|
||||
@@ -550,6 +550,7 @@ function ensureAceDryCards(){
|
||||
// defer until DOM ready
|
||||
window.addEventListener('DOMContentLoaded',function(){
|
||||
setLanguage(currentLang).catch(function(){});
|
||||
_loadSpoolmanStatus();
|
||||
// Kein Drucker konfiguriert? → direkt in den Drucker-Tab (zeigt "+ Drucker hinzufügen")
|
||||
fetch('/kx/printers').then(function(r){return r.json()}).then(function(d){
|
||||
if(!d.result||!d.result.length){showPanel('printers');loadPrinterTab();}
|
||||
|
||||
Reference in New Issue
Block a user