14 Commits
Author SHA1 Message Date
kkallas 834bad2bce Merge branch 'docs/technician-guide' into main
Technician guide (Markdown + PDF) with screenshots; USB 2.0 type-A plug requirement in the guide, README and the app's hints.
2026-09-30 15:46:00 +02:00
kkallasandClaude Opus 5.5 c41fa101b6 Technician guide as PDF (docs/INSTRUKCJA_TECHNIKA.pdf)
Printable A4 version of the guide with the screenshots, linked from the README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:45:51 +02:00
kkallasandClaude Opus 5.5 e299ef40f0 USB wording: a USB 2.0 type-A plug on the way; hubs are fine
Guide, README, quick start and flashing hints no longer say 'no hub' or 'directly to the laptop'; the requirement is a USB 2.0 type-A plug between box and computer (USB-C only is the failing case).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:41:12 +02:00
kkallasandClaude Opus 5.5 39f0d1718c Technician guide with screenshots; USB 2.0 type-A cable requirement
docs/INSTRUKCJA_TECHNIKA.md: install, update, connecting the box, reading
the Diagnosis panel, guided checks, Wi-Fi over USB, flashing, SD card,
service report, LED table and common problems, with screenshots of the
app rendered from a real v13 capture (docs/img). The box must be
connected with a USB 2.0 type-A cable directly to the computer; the
quick-start screen and README say so too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 15:39:02 +02:00
kkallas 6a62beb6aa Merge branch 'feature/wifi-over-usb' into main
Wi-Fi over USB tab (firmware v13 usb_console), LF line endings for all text files, live v13 test capture.
2026-09-30 13:58:53 +02:00
kkallasandClaude Opus 5.5 5bd14e1d5b Test: live v13 box answers USB commands
Capture from box 14:C1:9F:57:72:48 after flashing merged-binary-v13.bin: ping and wifi get replies, logs intact through the USB-Serial-JTAG driver.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 18:38:02 +02:00
kkallasandClaude Opus 5.5 ab420220e1 Wi-Fi over USB tab for firmware with the USB console (v13)
Writes / reads / removes the box's Wi-Fi over the serial port with the
usb_console commands (kota ping, wifi set|get|clear, health) and follows
the box through the restart until it joins the network. The password is
sent hex-encoded and never logged.

firmware/ now holds merged-binary-v13.bin (build 3ae273ec) instead of the
previous 1.0.16 build; error_ids.csv synced with the firmware.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:30:35 +02:00
kkallasandClaude Opus 5.5 0d21c5c205 Store all text files with LF line endings
Some files had been saved with CRLF on Windows, so a one-line change
showed as a whole-file diff. .gitattributes now stores text as LF
(.bat stays CRLF for cmd, .command/.sh LF for macOS).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 17:30:25 +02:00
kkallas 3fe45fa4d5 Merge pull request 'Feature/updater' (#2) from feature/updater into main
Reviewed-on: #2
2026-09-28 19:47:15 +02:00
kkallasandClaude Opus 5.5 1ab8af8fe2 README: fix two Windows paths
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 19:44:56 +02:00
kkallasandClaude Opus 5.5 bfbbd537d5 Updater messages without "!", README and changelog for v0.9
cmd drops "!" from messages when delayed expansion is on, so errors
read "ERROR:". README describes the two files per system and the
first install from a release zip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 19:43:50 +02:00
kkallasandClaude Opus 5.5 a33736742a Technician updater and one shared Python environment (v0.9.0)
update_windows.bat / update_macos.command: fetch release tags from Gitea,
move the folder to the newest vX.Y (git downloads only what changed),
connect a folder unpacked from a release zip on first run, install git/uv
when missing and sync the Python libraries. Developer copies on a branch
are left alone.

run_* and update_* share one environment (KotaTechnicianTool/venv)
instead of one per version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 19:42:25 +02:00
kkallas 724c2d62f9 Merge pull request 'README: install and update from Gitea instead of Google Drive folders' (#1) from docs/readme-gitea into main
Reviewed-on: #1
2026-09-28 19:36:35 +02:00
kkallasandClaude Opus 5.5 43f4c51aa4 README: install and update from Gitea instead of Google Drive folders
Describes the zip from Releases and git clone/pull, the macOS
executable-bit note for zips, and the branch/PR/tag workflow for the team.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 19:34:01 +02:00
33 changed files with 2205 additions and 23 deletions

No files matched your search

+2
View File
@@ -1,4 +1,6 @@
* text=auto eol=lf
*.command text eol=lf *.command text eol=lf
*.sh text eol=lf *.sh text eol=lf
*.bat text eol=crlf *.bat text eol=crlf
*.bin binary *.bin binary
*.png binary
+61 -13
View File
@@ -1,21 +1,52 @@
# KOTA Sensorbox Technician Tool v0.8 # KOTA Sensorbox Technician Tool
Diagnoza sensorboxa przez USB, wgrywanie firmware z folderu `firmware/` i przygotowanie karty SD. Diagnoza sensorboxa przez USB, wgrywanie firmware z folderu `firmware/` i przygotowanie karty SD.
Działa na Windows 10/11 i macOS 13 (Ventura) lub nowszym, na Macach z Intelem i Apple Silicon. Działa na Windows 10/11 i macOS 13 (Ventura) lub nowszym, na Macach z Intelem i Apple Silicon.
## Uruchomienie Repozytorium: https://gitea.kota-app.com/kkallas/kota-technician-tool (dostęp nadaje właściciel repozytorium).
**Windows:** dwuklik `run_windows.bat`. **Instrukcja krok po kroku ze zrzutami ekranu: [docs/INSTRUKCJA_TECHNIKA.md](docs/INSTRUKCJA_TECHNIKA.md) (do druku: [PDF](docs/INSTRUKCJA_TECHNIKA.pdf)).**
Box podłączaj tak, żeby po drodze była wtyczka USB 2.0 typu A (do komputera albo do huba).
**macOS:** dwuklik `run_macos.command`. ## Dla technika: dwa pliki
Jeśli Finder odpowie, że pliku nie można uruchomić (Google Drive gubi uprawnienie „wykonywalny”),
otwórz Terminal i jednorazowo wpisz `bash ` (ze spacją), przeciągnij plik `run_macos.command` do okna i naciśnij Enter.
Na stałe naprawia to: `chmod +x run_macos.command`.
Przy pierwszym uruchomieniu skrypt proponuje instalację `uv` (menedżer Pythona, instaluje się tylko dla bieżącego | System | Aktualizacja | Uruchomienie |
użytkownika) i pobiera biblioteki. Potrzebny jest internet, trwa to 1–2 minuty. Kolejne starty są natychmiastowe. |---|---|---|
Środowisko jest poza folderem Google Drive: | Windows | `update_windows.bat` | `run_windows.bat` |
`%LOCALAPPDATA%\KotaTechnicianTool\venv-0.8` (Windows), `~/Library/Caches/KotaTechnicianTool/venv-0.8` (macOS). | macOS | `update_macos.command` | `run_macos.command` |
- **Aktualizacja** sprawdza na Gitea najnowszą wydaną wersję i pobiera tylko to, co się zmieniło
(pliki programu, firmware i potrzebne biblioteki). Uruchom ją, gdy firmware team ogłosi nową wersję,
albo po prostu przed wyjazdem do klienta. Pokazuje, co się zmieniło.
- **Uruchomienie** startuje program. Nie łączy się z Gitea, działa też bez internetu (po pierwszej aktualizacji).
Nie trzymaj folderu narzędzia w Google Drive ani OneDrive.
## Pierwsza instalacja (raz na komputer)
1. Na Gitea otwórz **Releases** i przy najnowszej wersji pobierz **Source Code (ZIP)**.
2. Rozpakuj do zwykłego folderu, np. `Dokumenty\KOTA\technician-tool` (macOS: `~/Documents/KOTA/technician-tool`).
3. Uruchom plik aktualizacji dla swojego systemu. Za pierwszym razem:
- połączy folder z Gitea i zapyta o login do Gitea (hasło lub token); system je zapamięta,
- zainstaluje brakujące narzędzia za Twoją zgodą: Git (Windows: przez winget; macOS: Apple Command Line Tools
- po ich instalacji uruchom aktualizację jeszcze raz) oraz `uv` (menedżer Pythona, tylko dla bieżącego
użytkownika),
- pobierze biblioteki Pythona (1–2 minuty, potrzebny internet).
4. Uruchom program plikiem `run_...`.
**macOS:** jeśli Finder odpowie, że pliku nie można uruchomić (zdarza się po rozpakowaniu zip), otwórz Terminal,
wpisz `bash ` (ze spacją), przeciągnij `update_macos.command` do okna i naciśnij Enter. Po pierwszej aktualizacji
oba pliki `.command` dają się już otwierać dwuklikiem.
Zamiast zip można też zrobić `git clone https://gitea.kota-app.com/kkallas/kota-technician-tool.git` i dalej
używać tych samych dwóch plików.
Konkretna starsza wersja (np. do serwisu nietypowego boxa): w folderze narzędzia `git switch --detach v0.8`;
kolejna aktualizacja wraca do najnowszej.
Wszystkie wersje używają jednego środowiska Pythona poza folderem narzędzia:
`%LOCALAPPDATA%\KotaTechnicianTool\venv` (Windows), `~/Library/Caches/KotaTechnicianTool/venv` (macOS).
Stare środowiska `venv-0.x` z poprzednich wersji można usunąć.
Sesje, kopie zapasowe flash i ustawienia są w `~/KotaTechnicianTool` (Windows: `C:\Users\<użytkownik>\KotaTechnicianTool`). Sesje, kopie zapasowe flash i ustawienia są w `~/KotaTechnicianTool` (Windows: `C:\Users\<użytkownik>\KotaTechnicianTool`).
@@ -27,15 +58,32 @@ Sesje, kopie zapasowe flash i ustawienia są w `~/KotaTechnicianTool` (Windows:
Kabel USB musi przenosić dane (nie tylko ładowanie). Przy restartach z komunikatem o brownout użyj innego portu Kabel USB musi przenosić dane (nie tylko ładowanie). Przy restartach z komunikatem o brownout użyj innego portu
lub zasilacza. lub zasilacza.
## Wi-Fi przez USB (bez otwierania obudowy)
Zakładka **Wi-Fi (USB)**: podłącz box kablem USB, kliknij **Connect to the box**, wpisz nazwę sieci i hasło,
kliknij **Write to the box and connect**. Box zapisuje je na karcie SD, restartuje się i łączy z siecią
(zamiast Matter); zakładka pokazuje każdy krok aż do „Connected ... (signal -58 dBm)”.
**Read current Wi-Fi settings** pokazuje zapisaną sieć (bez hasła), **Remove Wi-Fi** wraca do Matter.
Wymaga firmware z komendami USB (plik `firmware/merged-binary-v13.bin` lub nowszy); starszy firmware
wgraj w zakładce **Flash firmware** (tryb App only zachowuje parowanie i ustawienia).
## Firmware ## Firmware
Wgrać można tylko pliki `.bin` z folderu `firmware/`. Lista pokazuje datę kompilacji zapisaną w pliku, Wgrać można tylko pliki `.bin` z folderu `firmware/`. Lista pokazuje datę kompilacji zapisaną w pliku,
najnowszy build jest na górze. Nowy build: wrzuć plik do `firmware/` i kliknij **Refresh list**. najnowszy build jest na górze. Nowy build: wrzuć plik do `firmware/` i kliknij **Refresh list**.
## Testy (dla zespołu) ## Dla zespołu
- Praca nad zmianą: gałąź (`git switch -c feature/<nazwa>`) → commity z przechodzącymi testami →
`git push -u origin feature/<nazwa>` → pull request na Gitea → merge do `main`.
- Wydanie wersji: numer w `pyproject.toml`, `kota_tech/__init__.py` i `uv.lock`, tag `vX.Y`
(`git tag -a vX.Y -m "Technician tool vX.Y"`, `git push origin vX.Y`), opis w **Releases** na Gitea.
Aktualizacja techników bierze **tylko tagi `v*`** – zmiany w `main` bez tagu do nich nie trafiają.
- Nie commitujemy `ENV.TXT` z prawdziwym tokenem ani haseł Wi-Fi.
- Testy:
``` ```
uv run --frozen pytest -q uv run --frozen pytest -q
``` ```
Zmiany: `docs/CHANGES-v0.7.md`, `docs/CHANGES-v0.8.md`. Zmiany w wersjach: `docs/CHANGES-v0.*.md`; historia v0.1–v0.8 jest w tagach gita.
+14
View File
@@ -0,0 +1,14 @@
# Technician tool v0.10 - changes (draft)
- New tab **Wi-Fi (USB)**: write the Wi-Fi name and password to the box's SD card over the USB cable, without
opening the case (firmware usb_console, `kota wifi set`). Shows each step: command support check, stored,
restart in Wi-Fi mode, connected with signal strength (polls `kota health`). Also reads the stored network
(`kota wifi get`, password never shown) and removes it (`kota wifi clear`, back to Matter).
- The password is sent hex-encoded, never written to the session log or the service report.
- Diagnosis: restarts `usb_wifi_set` / `usb_wifi_clear` are intentional (no "unexpected restart"); box
self-report shows the stored Wi-Fi network; `cmd health` replies update the health line.
- firmware/: `merged-binary-v13.bin` (usb_console, build 3ae273ec) replaces `merged-binary.bin` (build 4f10989e,
still in git tag v0.9). Note: v13 reports the same version 1.0.16 and compile date as the previous build;
the firmware team should bump the version for the next build.
- error_ids.csv updated from the firmware (E-CON-01).
- Test that builds the main window (catches start-up errors).
+9
View File
@@ -0,0 +1,9 @@
# Technician tool v0.9 - changes
- Two files per system for technicians: `update_windows.bat` / `update_macos.command` (update) and
`run_windows.bat` / `run_macos.command` (start).
- Update: checks Gitea for the newest release tag `vX.Y`, downloads only what changed (git), shows the list of
changes, protects files edited by hand (asks first), connects a folder unpacked from a release zip on first
run, installs git / uv when missing (asks first) and brings the Python libraries up to date.
- One shared Python environment for all versions: `KotaTechnicianTool/venv` (was `venv-0.x` per version).
- A developer copy on a branch is left alone by the update script (use `git pull`).
+204
View File
@@ -0,0 +1,204 @@
# KOTA Sensorbox Technician Tool – instrukcja dla technika
Program służy do sprawdzenia sensorboxa przez USB, podłączenia go do Wi-Fi bez otwierania obudowy,
wgrania firmware i przygotowania karty SD. Działa na Windows 10/11 i macOS 13 lub nowszym.
> ⚠️ **Między boxem a komputerem musi być po drodze wtyczka USB 2.0 typu A (prostokątna).**
> Może to być kabel USB 2.0 A wpięty do komputera albo do huba – hub jest w porządku.
> Połączenie wyłącznie przez USB-C (kabel USB-C–USB-C, przejściówka USB-C bez odcinka USB 2.0 A)
> często kończy się tym, że box nie jest widoczny w systemie („Unknown USB Device”) albo restartuje się przez
> spadki napięcia. Kabel musi przenosić dane – kabel „tylko do ładowania” nie zadziała.
---
## Spis treści
1. [Instalacja (raz na komputer)](#1-instalacja-raz-na-komputer)
2. [Aktualizacja i uruchomienie](#2-aktualizacja-i-uruchomienie)
3. [Podłączenie boxa](#3-podłączenie-boxa)
4. [Diagnoza boxa – zakładka Serial monitor](#4-diagnoza-boxa--zakładka-serial-monitor)
5. [Sprawdzenie krok po kroku – Guided troubleshooting](#5-sprawdzenie-krok-po-kroku--guided-troubleshooting)
6. [Wi-Fi przez USB – zakładka Wi-Fi (USB)](#6-wi-fi-przez-usb--zakładka-wi-fi-usb)
7. [Wgrywanie firmware – zakładka Flash firmware](#7-wgrywanie-firmware--zakładka-flash-firmware)
8. [Karta SD – zakładka SD card](#8-karta-sd--zakładka-sd-card)
9. [Raport serwisowy](#9-raport-serwisowy)
10. [Co oznacza kolor diody](#10-co-oznacza-kolor-diody)
11. [Najczęstsze problemy](#11-najczęstsze-problemy)
---
## 1. Instalacja (raz na komputer)
1. Na https://gitea.kota-app.com/kkallas/kota-technician-tool otwórz **Releases** i przy najnowszej wersji
pobierz **Source Code (ZIP)**.
2. Rozpakuj do zwykłego folderu, np. `Dokumenty\KOTA\technician-tool`
(macOS: `~/Documents/KOTA/technician-tool`). **Nie** do folderu Google Drive ani OneDrive.
3. Uruchom plik aktualizacji dla swojego systemu (patrz rozdział 2). Za pierwszym razem:
- zapyta o login do Gitea (hasło lub token) – system go zapamięta,
- za Twoją zgodą zainstaluje brakujące narzędzia (Git, `uv`),
- pobierze biblioteki (1–2 minuty, potrzebny internet).
**macOS:** jeśli Finder nie chce otworzyć pliku `.command`, otwórz Terminal, wpisz `bash ` (ze spacją),
przeciągnij plik do okna Terminala i naciśnij Enter. Po pierwszej aktualizacji dwuklik zaczyna działać.
## 2. Aktualizacja i uruchomienie
W folderze narzędzia potrzebujesz tylko dwóch plików:
| System | Aktualizacja | Uruchomienie |
|---|---|---|
| Windows | `update_windows.bat` | `run_windows.bat` |
| macOS | `update_macos.command` | `run_macos.command` |
- **Aktualizacja** – uruchom przed wyjazdem do klienta albo gdy zespół ogłosi nową wersję. Pobiera tylko zmiany
i pokazuje ich listę. Wymaga internetu.
- **Uruchomienie** – otwiera program. Działa bez internetu.
Po uruchomieniu otwiera się zakładka **Quick start** ze skróconą instrukcją i tabelą kolorów diody:
![Quick start](img/01_quick_start.png)
## 3. Podłączenie boxa
1. Włącz box włącznikiem z tyłu obudowy (**ON**). Samo zasilanie z laptopa może nie wystarczyć, szczególnie
przy słabej baterii.
2. Podłącz box tak, żeby **po drodze była wtyczka USB 2.0 typu A** – do portu USB-A komputera albo do huba
(patrz ostrzeżenie na górze).
3. Na liście portów box widać jako:
- Windows: `COMx - Sensorbox (native USB) [MAC]`
- macOS: `/dev/cu.usbmodemXXXX - Sensorbox (native USB) [MAC]`
MAC (np. `14:C1:9F:57:72:48`) to numer identyfikacyjny boxa – zapisz go w raporcie.
Jeśli boxa nie ma na liście, zobacz [Najczęstsze problemy](#11-najczęstsze-problemy).
## 4. Diagnoza boxa – zakładka Serial monitor
1. Wybierz port sensorboxa i kliknij **Connect**.
2. Kliknij **Reset & capture** – box uruchomi się ponownie, a program nagra cały start.
3. Poczekaj ok. **70 sekund** – co minutę box wysyła raport stanu (health), a program uzupełnia diagnozę.
![Serial monitor i diagnoza](img/02_serial_diagnosis.png)
Po lewej jest log z boxa, po prawej panel **Diagnosis** – czytaj go od góry:
| Element | Co oznacza |
|---|---|
| **Pasek na górze** | Werdykt: zielony = wszystko działa, żółty/czerwony = główny problem. |
| **Status LED should be** | Jaki kolor i wzór powinna mieć dioda. **Porównaj z boxem** – jeśli jest inaczej, zanotuj to. |
| **Firmware** | Wersja i build firmware na boxie. |
| **Box self-report** | Co box sam o sobie zgłasza: czujniki (I2C), karta SD, zegar, Matter, mikrofon, Wi-Fi, stan co minutę. ✔ = OK, ! = uwaga, ✖ = błąd. |
| **Start-up progress** | Kolejne etapy startu z czasem w sekundach. Szare kółko = etap jeszcze nieosiągnięty. |
| **Findings** | Znalezione problemy – najpierw przyczyny, pod nimi (↳) ich skutki. Kliknij, by zobaczyć, **co to znaczy** i **co zrobić**. |
Przydatne przyciski:
- **Show: KOTA diagnostics + errors** – pokazuje w logu tylko najważniejsze linie.
- **Copy report** – kopiuje diagnozę jako tekst (np. do maila).
- **Open logs folder** – pełne logi każdej sesji (do wysłania zespołowi firmware).
## 5. Sprawdzenie krok po kroku – Guided troubleshooting
Obok zakładki **Diagnosis** jest **Guided troubleshooting**. Program proponuje sprawdzenia pasujące do
znalezionych problemów. Zacznij od **Quick check – start here**:
![Lista sprawdzeń](img/03_guided_list.png)
Program zadaje pytania (np. jaki kolor ma dioda) i na bieżąco sprawdza log boxa. Odpowiedzi trafiają do raportu:
![Pytanie o kolor diody](img/04_guided_led_question.png)
## 6. Wi-Fi przez USB – zakładka Wi-Fi (USB)
Pozwala podłączyć box do sieci Wi-Fi **bez otwierania obudowy i wyjmowania karty SD**.
Wymaga firmware z komendami USB – jeśli program zgłosi „The box does not answer USB commands”, najpierw wgraj
najnowszy firmware (rozdział 7).
1. Kliknij **Connect to the box** (jeśli box nie jest już połączony w Serial monitor).
2. Opcjonalnie **Read current Wi-Fi settings** – pokazuje zapisaną sieć (hasła nigdy nie pokazuje).
3. Wpisz **nazwę sieci (SSID)** dokładnie jak na routerze i **hasło** (8–63 znaki).
Sieć musi być **2,4 GHz** i mieć hasło.
4. Kliknij **Write to the box and connect** i potwierdź.
5. Obserwuj listę kroków. Box zapisuje ustawienia, restartuje się i łączy z siecią. Na końcu zobaczysz
**„Connected to '…' (signal … dBm)”**:
![Wi-Fi przez USB](img/06_wifi_usb.png)
- Siła sygnału: powyżej −70 dBm jest dobrze, poniżej −75 dBm połączenie może się zrywać – przestaw box lub router.
- Po zapisaniu Wi-Fi box **nie używa Matter**. Powrót do Matter: **Remove Wi-Fi (back to Matter)**.
- Jeśli box nie połączy się w 90 s, sprawdź nazwę sieci, hasło i czy to sieć 2,4 GHz. Ustawienia zostają na
boxie, a box sam próbuje dalej.
## 7. Wgrywanie firmware – zakładka Flash firmware
![Wgrywanie firmware](img/05_flash.png)
1. **Sensorbox** – wybierz port. Program pokazuje, jaki firmware jest teraz na boxie i czy wybrany plik jest
nowszy.
2. **Firmware** – wybierz plik. Lista pokazuje **datę kompilacji**, najnowszy jest na górze. Dostępne są tylko
pliki z folderu `firmware` narzędzia (aktualizuje je `update_…`).
3. **Co wgrać:**
- **App only** (zalecane przy naprawach) – wymienia tylko program. Parowanie Matter, rejestracja aktualizacji
i ustawienia **zostają**.
- **Full image** – tylko dla nowych lub całkowicie wyczyszczonych płytek. **Kasuje parowanie Matter** – box
trzeba potem sparować od nowa. Wymaga zaznaczenia potwierdzenia.
- **Back up…** – kopia całej pamięci boxa przed wgraniem (ok. 3 minuty). Zalecane przy Full image.
4. Kliknij **Start flashing**. Nie odłączaj kabla, dopóki nie pojawi się **„Success”** – program sam uruchomi
box ponownie i sprawdzi, czy działa nowy firmware.
Jeśli wgrywanie nie może się połączyć: inny port/kabel (z wtyczką USB 2.0 A po drodze), zamknij inne programy używające
portu. Ostateczność (trzeba otworzyć obudowę): przytrzymaj **BOOT**, naciśnij i puść **RESET**, puść **BOOT**,
kliknij Start jeszcze raz.
## 8. Karta SD – zakładka SD card
Karta SD jest **wewnątrz obudowy**. Ta zakładka służy do przygotowania nowej karty albo naprawy uszkodzonej.
Do zmiany samego Wi-Fi używaj zakładki **Wi-Fi (USB)** – nie trzeba wtedy otwierać obudowy.
![Karta SD](img/07_sd_card.png)
1. **Settings** – ustawienia wczytują się z pliku od zespołu (INFLUX_URL, INFLUX_TOKEN). Nie zmieniaj ich bez
potrzeby. Opcjonalnie możesz wpisać Wi-Fi (sieć i hasło).
2. Włóż kartę do czytnika w komputerze. Na liście pojawiają się tylko karty wymienne – dyski komputera nie są
pokazywane.
3. **Check card** – sprawdza kartę bez zmieniania czegokolwiek.
**Write ENV.TXT only** – zapisuje ustawienia, zostawia pomiary na karcie.
**Format card and write ENV.TXT** – kasuje całą kartę (FAT32) i zapisuje ustawienia.
4. Program sam wysuwa kartę – dopiero wtedy ją wyjmij.
## 9. Raport serwisowy
Kliknij **Service report…** w zakładce Serial monitor. Otworzy się strona boxa w systemie KOTA Serwis
z wpisaną diagnozą (werdykt, stan boxa, etapy startu, problemy z liczbą wystąpień i czasem). Sprawdź treść,
dopisz lokalizację i uwagi, kliknij **Zapisz**.
Zaznaczenie **Open service report on disconnect** otwiera raport automatycznie po rozłączeniu boxa.
## 10. Co oznacza kolor diody
| Kolor | Wzór | Znaczenie | Co zrobić |
|---|---|---|---|
| Zielony | ciągły | Wszystko OK | Nic |
| Cyan (turkusowy) | pulsuje / szybko miga | Nie sparowany w Matter / telefon łączy się | Sparuj w aplikacji Matter albo ustaw Wi-Fi przez USB |
| Biały | szybko miga / ciągły / pulsuje | Błąd karty SD lub ENV.TXT / reset fabryczny / tryb konfiguracji Wi-Fi | Sprawdź kartę SD (zakładka SD card) |
| Czerwony | 1–6 błysków | Awaria czujnika: 1 BME688, 2 SEN66, 3 AS7341, 4 mikrofon, 5 flicker, 6 test po aktualizacji | Policz błyski, sprawdź przewód tego czujnika |
| Czerwony | ciągły | Inny błąd wewnętrzny / brak pamięci | Zapisz log, wyślij zespołowi |
| Niebieski | 1 / 2 błyski | Zegar RTC nie odpowiada / zablokowana magistrala I2C | Sprawdź przewód I2C między płytkami |
| Fioletowy | ciągły / miga | Brak sieci / serwer odrzuca box (złe ENV.TXT) | Sprawdź Wi-Fi / wgraj poprawne ENV.TXT |
| Żółty | miga coraz szybciej | Pobiera aktualizację | Nie wyłączaj, poczekaj |
| Pomarańczowy | ciągły | Test po aktualizacji (~2,5 min) | Poczekaj |
| Zgaszona | – | Firmware nie działa lub brak zasilania | Sprawdź włącznik i kabel; wgraj firmware |
Mała dioda obok (heartbeat): miga raz na sekundę = online, podwójnie = offline, nie miga = firmware stoi.
## 11. Najczęstsze problemy
| Objaw | Przyczyna | Co zrobić |
|---|---|---|
| Boxa nie ma na liście portów | Brak wtyczki USB 2.0 A po drodze (samo USB-C), kabel tylko do ładowania, box wyłączony | **Połączenie z wtyczką USB 2.0 typu A** (do komputera lub huba), kabel z transmisją danych, włącznik ON, odłącz i podłącz ponownie. W Windows sprawdź Menedżer urządzeń – „Unknown USB Device” oznacza problem z kablem/portem/zasilaniem. |
| Diagnoza: „Power supply voltage drops (brown-out)”, box się restartuje | Za słabe zasilanie | Włącznik boxa ON, inny port USB-A, zasilacz; naładuj baterię |
| „The box does not answer USB commands” (Wi-Fi USB) | Stary firmware | Wgraj najnowszy firmware (App only) |
| „Clock chip was stopped at start-up” | Pusta bateria zegara RTC | Zegar ustawi się sam po połączeniu z internetem; przy powtórce wymień baterię pastylkową |
| „Box is not connected to Wi-Fi (not commissioned in Matter)” | Box nie jest sparowany | Sparuj w Matter (przycisk **Matter pairing QR code…**) albo ustaw Wi-Fi przez USB |
| Wgrywanie nie może połączyć się z boxem | Port zajęty lub zły kabel | Zamknij inne programy, inny kabel/port; ostatecznie BOOT + RESET (rozdział 7) |
Jeśli problem się powtarza: **Open logs folder** → wyślij plik sesji zespołowi firmware razem z MAC boxa.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

+1 -1
View File
@@ -1,3 +1,3 @@
"""KOTA sensorbox technician tool.""" """KOTA sensorbox technician tool."""
__version__ = "0.8.0" __version__ = "0.9.0"
+22
View File
@@ -335,6 +335,8 @@ class DiagnosticsEngine:
self.matter_qr: str | None = None # "KOTA: matter ... qr=MT:..." self.matter_qr: str | None = None # "KOTA: matter ... qr=MT:..."
self.matter_manual: str | None = None self.matter_manual: str | None = None
self.kota_seen = False # firmware prints KOTA: lines self.kota_seen = False # firmware prints KOTA: lines
self.console_api: int | None = None # "cmd ping ... api=N": box accepts USB commands
self.wifi_config: dict[str, str] | None = None # last "cmd wifi_get" reply (never a password)
self._reset_led_state() self._reset_led_state()
def _reset_led_state(self) -> None: def _reset_led_state(self) -> None:
@@ -714,6 +716,20 @@ class DiagnosticsEngine:
fd = self._custom(key, Severity[sev.upper()], title, meaning, actions, expl) fd = self._custom(key, Severity[sev.upper()], title, meaning, actions, expl)
self._touch(fd, line) self._touch(fd, line)
def _kota_cmd(self, line: LogLine, f: dict[str, str]) -> None:
"""Replies to commands sent by this tool (firmware usb_console)."""
name = line.words[0] if line.words else ""
if f.get("ok") != "1":
return # the Wi-Fi tab reports failures itself
if name == "ping":
api = f.get("api", "")
self.console_api = int(api) if api.isdigit() else None
elif name == "health":
self.boot.kota["health"] = line # same fields as the periodic health line
self._kota_health(line, f)
elif name == "wifi_get":
self.wifi_config = {k: f.get(k, "?") for k in ("ssid", "password_set", "mode")}
def _kota_led(self, line: LogLine, f: dict[str, str]) -> None: def _kota_led(self, line: LogLine, f: dict[str, str]) -> None:
if "previous_boot" in line.words: if "previous_boot" in line.words:
code = f.get("code", "0") code = f.get("code", "0")
@@ -845,6 +861,12 @@ class DiagnosticsEngine:
if ln := k.get("mic"): if ln := k.get("mic"):
on = ln.fields.get("enabled") == "1" on = ln.fields.get("enabled") == "1"
out.append(("Microphone", "on" if on else "switched OFF (switch on the back)", "ok" if on else "info")) out.append(("Microphone", "on" if on else "switched OFF (switch on the back)", "ok" if on else "info"))
if self.wifi_config:
from ..serialio.commands import unhex_utf8
w = self.wifi_config
ssid = unhex_utf8(w["ssid"])
out.append(("Wi-Fi config", (f"network '{ssid}', password {'set' if w['password_set'] == '1' else 'NOT set'}"
if ssid else "no network on the SD card") + f", mode {w['mode']}", "info"))
if ln := k.get("health"): if ln := k.get("health"):
f = ln.fields f = ln.fields
wifi = f.get("wifi", "?") wifi = f.get("wifi", "?")
+1
View File
@@ -191,3 +191,4 @@ E-GATH-01,GATH,error,Failed to take line protocol mutex,Internal error - send th
E-GATH-02,GATH,error,Failed to get line protocol from sensor,Device ran out of memory; restart it and send the log to the firmware team E-GATH-02,GATH,error,Failed to get line protocol from sensor,Device ran out of memory; restart it and send the log to the firmware team
E-GATH-03,GATH,error,Failed to create task for sensor,Internal error - send the log to the firmware team E-GATH-03,GATH,error,Failed to create task for sensor,Internal error - send the log to the firmware team
E-GATH-04,GATH,error,Failed to create main gather task,Internal error - send the log to the firmware team E-GATH-04,GATH,error,Failed to create main gather task,Internal error - send the log to the firmware team
E-CON-01,CON,error,Failed to install USB-Serial-JTAG driver: %s,Internal error - send the log to the firmware team
1 id module severity message action
191 E-GATH-02 GATH error Failed to get line protocol from sensor Device ran out of memory; restart it and send the log to the firmware team
192 E-GATH-03 GATH error Failed to create task for sensor Internal error - send the log to the firmware team
193 E-GATH-04 GATH error Failed to create main gather task Internal error - send the log to the firmware team
194 E-CON-01 CON error Failed to install USB-Serial-JTAG driver: %s Internal error - send the log to the firmware team
+1
View File
@@ -39,6 +39,7 @@ I2C_DEVICES = {"0x39": "AS7341", "0x68": "DS1307", "0x6B": "SEN66", "0x76": "BME
INTENTIONAL_RESTARTS = { INTENTIONAL_RESTARTS = {
"ota_update", "button_provisioning_abort", "button_wifi_cleared", "ota_update", "button_provisioning_abort", "button_wifi_cleared",
"button_provisioning_toggle", "provisioning_saved", "button_provisioning_toggle", "provisioning_saved",
"usb_wifi_set", "usb_wifi_clear", # Wi-Fi changed from the technician tool (usb_console)
} }
MODULES = { MODULES = {
+1 -1
View File
@@ -26,7 +26,7 @@ HINTS = [
"The box did not enter flashing mode by itself. Open the case, hold the BOOT button, press and release RESET, " "The box did not enter flashing mode by itself. Open the case, hold the BOOT button, press and release RESET, "
"release BOOT, then press Start again."), "release BOOT, then press Start again."),
(re.compile(r"device reports readiness to read but returned no data|The port disappeared|device disconnected", re.I), (re.compile(r"device reports readiness to read but returned no data|The port disappeared|device disconnected", re.I),
"The USB connection dropped. Use a short data-capable USB cable directly on the laptop (no hub) and try again."), "The USB connection dropped. Use a data-capable cable with a USB 2.0 type-A plug on the way to the laptop (not USB-C only) and try again."),
(re.compile(r"Invalid head of packet|timed out", re.I), (re.compile(r"Invalid head of packet|timed out", re.I),
"Communication errors. Try another USB cable or port."), "Communication errors. Try another USB cable or port."),
] ]
+283
View File
@@ -0,0 +1,283 @@
"""Commands to the box over the USB serial port (firmware with usb_console, api=1).
Protocol (kota-sensorboard main/usb_console.hpp): ASCII lines "kota ...",
one reply line each, logged as "KOTA: cmd <name> ok=1|0 [key=value ...]":
kota ping -> cmd ping ok=1 fw=<version> api=1
kota health -> cmd health ok=1 <health fields> | ok=0 err=not_ready
kota wifi get -> cmd wifi_get ok=1 ssid=<hex|-> password_set=0|1 mode=...
kota wifi set <ssid_hex> <pass_hex> -> cmd wifi_set ok=1 restart=1, then restart (usb_wifi_set)
kota wifi clear -> cmd wifi_clear ok=1 restart=1, then restart (usb_wifi_clear)
Firmware without the console never answers. The password is only ever sent
hex-encoded and is never written to the log by the box or by this tool.
WifiFlow runs a whole "write / clear Wi-Fi" job as a small state machine
driven by `feed(line)` and `tick(now)`, so it is testable without Qt or a box.
"""
from __future__ import annotations
import enum
import time
from collections.abc import Callable
from dataclasses import dataclass, field
from ..core.logline import LineKind, LogLine
API_VERSION = 1
# Technician-facing text for the firmware's err= codes.
ERRORS = {
"bad_args": "The box did not understand the command (tool/firmware mismatch).",
"bad_hex": "The box could not decode the settings (tool/firmware mismatch).",
"bad_char": "The name or password contains a line break.",
"ssid_length": "The network name must be 1-32 bytes.",
"password_length": "The password must be 8-63 characters.",
"sd_not_mounted": "The box cannot read its SD card, so it cannot store the settings.",
"write_failed": "Writing ENV.TXT on the SD card failed.",
"verify_failed": "ENV.TXT did not read back correctly after writing.",
"unknown_command": "This firmware does not know the command.",
"not_ready": "The box is still starting; try again in a few seconds.",
}
def hex_utf8(text: str) -> str:
return text.encode("utf-8").hex()
def unhex_utf8(value: str) -> str | None:
if not value or value == "-":
return None
try:
return bytes.fromhex(value).decode("utf-8", errors="replace")
except ValueError:
return None
def validate_wifi(ssid: str, password: str) -> list[str]:
"""Same limits as the firmware (usb_console.cpp); empty list = OK."""
problems = []
if not ssid:
problems.append("Enter the Wi-Fi network name (SSID).")
elif len(ssid.encode("utf-8")) > 32:
problems.append("The network name is longer than 32 bytes.")
if not 8 <= len(password.encode("utf-8")) <= 63:
problems.append("The password must be 8-63 characters (WPA2). Open networks are not supported.")
if any(c in ssid + password for c in "\r\n\0"):
problems.append("The name or password contains a line break.")
return problems
def wifi_set_command(ssid: str, password: str) -> str:
problems = validate_wifi(ssid, password)
if problems:
raise ValueError(" ".join(problems))
return f"kota wifi set {hex_utf8(ssid)} {hex_utf8(password)}"
def loggable(command: str) -> str:
"""The command as it may appear in the session log: never the password."""
parts = command.split()
if parts[:3] == ["kota", "wifi", "set"] and len(parts) == 5:
return f"kota wifi set (network '{unhex_utf8(parts[3])}', password hidden)"
return command
@dataclass(frozen=True)
class Reply:
name: str # ping | health | wifi_get | wifi_set | wifi_clear | unknown
ok: bool
fields: dict[str, str]
@property
def error(self) -> str:
code = self.fields.get("err", "")
return ERRORS.get(code, f"The box reported an error ({code or 'unknown'}).")
def parse_reply(line: LogLine) -> Reply | None:
"""'I (5) KOTA: cmd wifi_set ok=1 restart=1' -> Reply('wifi_set', True, {...})."""
if line.kind != LineKind.KOTA or line.record != "cmd" or not line.words:
return None
return Reply(line.words[0], line.fields.get("ok") == "1", dict(line.fields))
@dataclass(frozen=True)
class WifiInfo:
"""What `kota wifi get` reported."""
ssid: str | None
password_set: bool
mode: str
@classmethod
def from_reply(cls, r: Reply) -> WifiInfo:
return cls(unhex_utf8(r.fields.get("ssid", "-")), r.fields.get("password_set") == "1",
r.fields.get("mode", "?"))
def describe(self) -> str:
mode = {"wifi": "local Wi-Fi from the SD card", "matter": "Matter (Wi-Fi given by the Matter app)",
"provisioning": "Wi-Fi setup portal"}.get(self.mode, self.mode)
net = f"network '{self.ssid}'" + (", password set" if self.password_set else ", NO password")
return f"Mode: {mode}. " + (net if self.ssid else "No network stored on the SD card.")
# ------------------------------------------------------------------ flows
class Step(str, enum.Enum):
PING = "Checking the box accepts USB commands"
READ = "Reading the Wi-Fi settings"
SEND = "Storing the settings on the box's SD card"
RESTART = "Waiting for the box to restart"
CONNECT = "Waiting for the box to join the Wi-Fi network"
DONE = "Done"
FAILED = "Failed"
@dataclass
class FlowEvent:
step: Step
text: str
ok: bool | None = None # None = in progress, True = finished OK, False = failed
PING_TIMEOUT_S = 3.0
REPLY_TIMEOUT_S = 8.0
RESTART_TIMEOUT_S = 40.0
CONNECT_TIMEOUT_S = 90.0
HEALTH_POLL_S = 5.0
@dataclass
class WifiFlow:
"""One technician job: "read", "set" (ssid+password) or "clear".
`send(text)` writes one command line to the box (returns False when the
port is not connected); `on_event` reports progress for the UI.
"""
action: str
send: Callable[[str], bool]
on_event: Callable[[FlowEvent], None]
ssid: str = ""
password: str = ""
now: Callable[[], float] = time.monotonic
step: Step = Step.PING
info: WifiInfo | None = None
_deadline: float = 0.0
_next_poll: float = 0.0
_events: list[FlowEvent] = field(default_factory=list)
@property
def finished(self) -> bool:
return self.step in (Step.DONE, Step.FAILED)
def start(self) -> None:
if self.action == "set":
problems = validate_wifi(self.ssid, self.password)
if problems:
return self._fail(" ".join(problems))
self._go(Step.PING, "kota ping", PING_TIMEOUT_S)
def cancel(self) -> None:
if not self.finished:
self._fail("Cancelled.")
# -------------------------------------------------------- driving
def feed(self, line: LogLine) -> None:
if self.finished:
return
if self.step == Step.RESTART and line.kind == LineKind.KOTA and line.record == "boot":
return self._on_boot(line.fields)
r = parse_reply(line)
if r is None:
return
if self.step == Step.PING and r.name == "ping":
if not r.ok or int(r.fields.get("api", "0") or 0) < API_VERSION:
return self._fail("The box answered, but its command version is not supported.")
self._emit(f"Firmware {r.fields.get('fw', '?')} accepts USB commands.", True)
if self.action == "read":
return self._go(Step.READ, "kota wifi get", REPLY_TIMEOUT_S)
if self.action == "set":
return self._go(Step.SEND, wifi_set_command(self.ssid, self.password), REPLY_TIMEOUT_S)
return self._go(Step.SEND, "kota wifi clear", REPLY_TIMEOUT_S)
if self.step == Step.READ and r.name == "wifi_get":
if not r.ok:
return self._fail(r.error)
self.info = WifiInfo.from_reply(r)
return self._finish(self.info.describe())
if self.step == Step.SEND and r.name in ("wifi_set", "wifi_clear"):
if not r.ok:
return self._fail(r.error)
self._emit("The box stored the settings and is restarting.", True)
self.step, self._deadline = Step.RESTART, self.now() + RESTART_TIMEOUT_S
return self._emit(Step.RESTART.value + "...")
if self.step == Step.CONNECT and r.name == "health" and r.ok:
return self._on_health(r.fields)
def tick(self) -> None:
"""Call periodically (e.g. every 0.5 s): timeouts and health polling."""
if self.finished:
return
t = self.now()
if self.step == Step.CONNECT and t >= self._next_poll:
self._next_poll = t + HEALTH_POLL_S
self.send("kota health")
if t < self._deadline:
return
if self.step == Step.PING:
self._fail("The box does not answer USB commands. It needs firmware with the USB console "
"(Flash firmware tab), or it is still starting - try again in 10 s.")
elif self.step == Step.RESTART:
self._fail("The box stored the settings but no restart was seen. Press Reset & capture in the "
"Serial monitor and check the Diagnosis panel.")
elif self.step == Step.CONNECT:
self._fail(f"The box did not join '{self.ssid}' within {int(CONNECT_TIMEOUT_S)} s. Check the network "
"name and password, that it is a 2.4 GHz network and that it is in range. The settings stay "
"on the box; it keeps retrying.")
else:
self._fail("The box did not answer. Check the USB connection and try again.")
# -------------------------------------------------------- internals
def _on_boot(self, f: dict[str, str]) -> None:
mode, last = f.get("mode", "?"), f.get("last_restart", "?")
want = "usb_wifi_set" if self.action == "set" else "usb_wifi_clear"
if last != want:
return self._fail(f"The box restarted for another reason ({last}); the settings may not be applied.")
self._emit(f"Restarted in {mode} mode.", True)
if self.action == "clear":
ok = mode == "matter"
return self._finish("Wi-Fi removed; the box uses Matter again (pair it in the Matter app if needed).") \
if ok else self._fail(f"The box restarted in {mode} mode instead of Matter.")
if mode != "wifi":
return self._fail(f"The box restarted in {mode} mode instead of local Wi-Fi.")
self.step = Step.CONNECT
self._deadline = self.now() + CONNECT_TIMEOUT_S
self._next_poll = self.now() + HEALTH_POLL_S
self._emit(Step.CONNECT.value + f" '{self.ssid}'...")
def _on_health(self, f: dict[str, str]) -> None:
if f.get("wifi") != "connected":
return
rssi = f.get("rssi", "?")
note = " - weak signal, consider moving the box or the router" if rssi.lstrip("-").isdigit() \
and int(rssi) < -75 else ""
self._finish(f"Connected to '{self.ssid}' (signal {rssi} dBm{note}). Data upload starts within a minute.")
def _go(self, step: Step, command: str, timeout: float) -> None:
self.step, self._deadline = step, self.now() + timeout
self._emit(step.value + "...")
if not self.send(command):
self._fail("The box is not connected. Connect it first.")
def _emit(self, text: str, ok: bool | None = None) -> None:
ev = FlowEvent(self.step, text, ok)
self._events.append(ev)
self.on_event(ev)
def _finish(self, text: str) -> None:
self.step = Step.DONE
self._emit(text, True)
def _fail(self, text: str) -> None:
self.step = Step.FAILED
self._emit(text, False)
+2 -1
View File
@@ -54,7 +54,8 @@ HINTS = [
STEPS = [ STEPS = [
"Switch the sensorbox <b>power switch ON</b>.", "Switch the sensorbox <b>power switch ON</b>.",
"Connect the laptop to the box's <b>native USB</b> port with a data-capable cable.", "Connect the box so that a <b>USB 2.0 type-A plug</b> is on the way to the laptop (into the laptop or a "
"hub; USB-C only often fails). The cable must carry data.",
"Open the <b>Serial monitor</b> tab, choose the sensorbox port, press " "Open the <b>Serial monitor</b> tab, choose the sensorbox port, press "
"<b>Connect</b>.", "<b>Connect</b>.",
"Press <b>Reset &amp; capture</b> to record a full boot log from the first line.", "Press <b>Reset &amp; capture</b> to record a full boot log from the first line.",
+1 -1
View File
@@ -36,7 +36,7 @@ BACKUP_DIR = SESSIONS_DIR.parent / "backups"
VERIFY_TIMEOUT_MS = 45_000 VERIFY_TIMEOUT_MS = 45_000
HELP = ( HELP = (
"<b>If flashing cannot connect:</b> use a data-capable USB cable directly on the laptop, close " "<b>If flashing cannot connect:</b> use a data-capable cable with a USB 2.0 type-A plug on the way, close "
"other programs using the port, then retry. Last resort (case must be opened): hold <b>BOOT</b>, " "other programs using the port, then retry. Last resort (case must be opened): hold <b>BOOT</b>, "
"press and release <b>RESET</b>, release <b>BOOT</b>, and press Start again." "press and release <b>RESET</b>, release <b>BOOT</b>, and press Start again."
) )
+40
View File
@@ -28,6 +28,7 @@ from ..core.logline import LineKind, LogLine, host_event
from ..core.session import SessionLog from ..core.session import SessionLog
from ..diag.engine import DiagnosticsEngine from ..diag.engine import DiagnosticsEngine
from ..diag.guides import GuideRunner from ..diag.guides import GuideRunner
from ..serialio.commands import loggable
from ..serialio.manager import SerialManager, State from ..serialio.manager import SerialManager, State
from ..serialio.ports import PortInfo, list_serial_ports from ..serialio.ports import PortInfo, list_serial_ports
from ..matter.payload import SetupPayload, payload_from_log from ..matter.payload import SetupPayload, payload_from_log
@@ -38,6 +39,7 @@ from .flash_tab import FlashTab
from .matter_qr import MatterQrDialog from .matter_qr import MatterQrDialog
from .guide_panel import GuidePanel from .guide_panel import GuidePanel
from .sd_tab import SdTab from .sd_tab import SdTab
from .wifi_tab import WifiTab
MAX_LINES = 20000 MAX_LINES = 20000
# "KOTA" = the firmware's structured diagnostic lines (1.0.16+) plus errors. # "KOTA" = the firmware's structured diagnostic lines (1.0.16+) plus errors.
@@ -76,6 +78,7 @@ class SerialTab(QWidget):
self._engine = DiagnosticsEngine() self._engine = DiagnosticsEngine()
self._diag_dirty = True self._diag_dirty = True
self._runner = GuideRunner(self._engine, on_action=self._guide_action, on_log=self._guide_log) self._runner = GuideRunner(self._engine, on_action=self._guide_action, on_log=self._guide_log)
self._line_listeners: list = [] # other tabs following the live log (Wi-Fi over USB)
# --- controls # --- controls
self.port_combo = QComboBox(minimumWidth=320) self.port_combo = QComboBox(minimumWidth=320)
@@ -237,6 +240,39 @@ class SerialTab(QWidget):
def engine(self) -> DiagnosticsEngine: def engine(self) -> DiagnosticsEngine:
return self._engine return self._engine
# ---- commands to the box (firmware usb_console) -----------------------
@property
def is_connected(self) -> bool:
return self._manager.state == State.CONNECTED
@property
def active_port(self) -> PortInfo | None:
return self._active_port if self._manager.is_running else None
def add_line_listener(self, callback) -> None:
self._line_listeners.append(callback)
def send_command(self, command: str) -> bool:
"""Write one "kota ..." line to the box; False when not connected.
The session log gets the command without the Wi-Fi password."""
if not self.is_connected:
return False
self._manager.write((command + "\n").encode("ascii"))
if not command.startswith(("kota health", "kota ping")): # polled; would flood the log
self._guide_log(f"sent to the box: {loggable(command)}")
return True
def connect_first_box(self) -> bool:
"""Connect to the first sensorbox port found (for tabs that need the box)."""
if self._manager.is_running:
return True
self.refresh_ports()
port = next((p for p in self._ports if p.is_sensorbox), None)
if port is None:
return False
self.connect_port(port, capture=False)
return True
def release_port(self) -> None: def release_port(self) -> None:
"""Stop monitoring so esptool can open the port exclusively.""" """Stop monitoring so esptool can open the port exclusively."""
if self._manager.is_running: if self._manager.is_running:
@@ -293,6 +329,8 @@ class SerialTab(QWidget):
self._session.write(line) self._session.write(line)
self._engine.feed(line) self._engine.feed(line)
self._runner.feed(line) self._runner.feed(line)
for listener in self._line_listeners:
listener(line)
self._diag_dirty = True self._diag_dirty = True
if line.kind == LineKind.BOOT: if line.kind == LineKind.BOOT:
self._counts["boots"] += 1 self._counts["boots"] += 1
@@ -402,6 +440,8 @@ class MainWindow(QMainWindow):
tabs.addTab(guide, "Quick start") tabs.addTab(guide, "Quick start")
tabs.addTab(self.serial_tab, "Serial monitor") tabs.addTab(self.serial_tab, "Serial monitor")
tabs.addTab(self.flash_tab, "Flash firmware") tabs.addTab(self.flash_tab, "Flash firmware")
self.wifi_tab = WifiTab(self.serial_tab)
tabs.addTab(self.wifi_tab, "Wi-Fi (USB)")
self.sd_tab = SdTab(self.serial_tab) self.sd_tab = SdTab(self.serial_tab)
tabs.addTab(self.sd_tab, "SD card") tabs.addTab(self.sd_tab, "SD card")
self.setCentralWidget(tabs) self.setCentralWidget(tabs)
+207
View File
@@ -0,0 +1,207 @@
"""Wi-Fi over USB: read / write / remove the box's Wi-Fi without opening the case.
Needs firmware with the USB console (usb_console, api=1). The job itself is
serialio.commands.WifiFlow; this tab only collects the input and shows the
steps. Lines arrive from the Serial monitor's connection (one port owner).
"""
from __future__ import annotations
from PySide6.QtCore import Qt, QTimer
from PySide6.QtWidgets import (
QCheckBox,
QFormLayout,
QGroupBox,
QHBoxLayout,
QLabel,
QLineEdit,
QListWidget,
QListWidgetItem,
QMessageBox,
QPushButton,
QVBoxLayout,
QWidget,
)
from PySide6.QtGui import QBrush, QColor
from ..core.logline import LogLine
from ..serialio.commands import FlowEvent, WifiFlow, validate_wifi
INTRO = (
"Stores the Wi-Fi name and password on the box's SD card over the USB cable - <b>no need to open the "
"case</b>. The box then restarts and uses this network instead of Matter. Needs firmware with USB commands "
"(<i>Flash firmware</i> tab, newest file). Only 2.4 GHz networks with a password (8-63 characters)."
)
MARK = {True: ("✔", "#1b7a33"), False: ("✖", "#b03a2e"), None: ("…", "#2e6da4")}
class WifiTab(QWidget):
def __init__(self, serial_tab, parent: QWidget | None = None):
super().__init__(parent)
self.serial_tab = serial_tab
self._flow: WifiFlow | None = None
intro = QLabel(INTRO, wordWrap=True)
# 1. box
box = QGroupBox("1. Sensorbox")
self.box_state = QLabel(wordWrap=True)
self.connect_btn = QPushButton("Connect to the box")
self.connect_btn.clicked.connect(self._connect)
self.read_btn = QPushButton("Read current Wi-Fi settings")
self.read_btn.clicked.connect(lambda: self._run("read"))
bl = QVBoxLayout(box)
bl.addWidget(self.box_state)
brow = QHBoxLayout()
brow.addWidget(self.connect_btn)
brow.addWidget(self.read_btn)
brow.addStretch(1)
bl.addLayout(brow)
# 2. network
net = QGroupBox("2. Wi-Fi network for this box")
self.ssid = QLineEdit(placeholderText="network name (SSID), exactly as on the router")
self.password = QLineEdit(placeholderText="8-63 characters")
self.password.setEchoMode(QLineEdit.EchoMode.Password)
show = QCheckBox("Show password")
show.toggled.connect(lambda on: self.password.setEchoMode(
QLineEdit.EchoMode.Normal if on else QLineEdit.EchoMode.Password))
form = QFormLayout()
form.addRow("Network (SSID)", self.ssid)
prow = QHBoxLayout()
prow.addWidget(self.password, 1)
prow.addWidget(show)
form.addRow("Password", prow)
self.input_problem = QLabel(wordWrap=True)
self.input_problem.setStyleSheet("color:#b03a2e")
self.write_btn = QPushButton("Write to the box and connect")
self.write_btn.setMinimumHeight(34)
self.write_btn.clicked.connect(lambda: self._run("set"))
self.clear_btn = QPushButton("Remove Wi-Fi (back to Matter)")
self.clear_btn.clicked.connect(self._clear)
nl = QVBoxLayout(net)
nl.addLayout(form)
nl.addWidget(self.input_problem)
arow = QHBoxLayout()
arow.addWidget(self.write_btn)
arow.addWidget(self.clear_btn)
arow.addStretch(1)
nl.addLayout(arow)
# 3. progress
prog = QGroupBox("3. Progress")
self.steps = QListWidget()
self.steps.setSelectionMode(QListWidget.SelectionMode.NoSelection)
self.result = QLabel(wordWrap=True)
self.result.setMargin(8)
self.result.setVisible(False)
self.cancel_btn = QPushButton("Cancel")
self.cancel_btn.clicked.connect(self._cancel)
pl = QVBoxLayout(prog)
pl.addWidget(self.steps)
pl.addWidget(self.result)
pl.addWidget(self.cancel_btn, 0, Qt.AlignmentFlag.AlignLeft)
lay = QVBoxLayout(self)
lay.addWidget(intro)
lay.addWidget(box)
lay.addWidget(net)
lay.addWidget(prog, 1)
serial_tab.add_line_listener(self._on_line)
for w in (self.ssid, self.password):
w.textChanged.connect(self._update)
self._timer = QTimer(self, interval=500)
self._timer.timeout.connect(self._tick)
self._timer.start()
self._update()
# ------------------------------------------------------------ state
def showEvent(self, event): # noqa: N802 - refresh when the tab is opened
self._update()
super().showEvent(event)
def _update(self) -> None:
connected = self.serial_tab.is_connected
busy = self._flow is not None and not self._flow.finished
port = self.serial_tab.active_port
eng = self.serial_tab.engine
if connected and port:
fw = eng.firmware.describe() if eng.firmware.elf_sha else "firmware not identified yet"
api = {None: "", 1: " - USB commands supported"}.get(eng.console_api, f" - USB commands api {eng.console_api}")
self.box_state.setText(f"Connected: <b>{port.label}</b><br><small>{fw}{api}</small>")
elif self.serial_tab.active_port:
self.box_state.setText("Waiting for the box... (it may be restarting)")
else:
self.box_state.setText("Not connected. Plug in the sensorbox (native USB) and press "
"<b>Connect to the box</b>.")
problems = validate_wifi(self.ssid.text(), self.password.text())
typed = bool(self.ssid.text() or self.password.text())
self.input_problem.setText(" ".join(problems) if typed else "")
self.connect_btn.setVisible(not self.serial_tab.active_port)
for w in (self.read_btn, self.clear_btn):
w.setEnabled(connected and not busy)
self.write_btn.setEnabled(connected and not busy and not problems)
self.ssid.setEnabled(not busy)
self.password.setEnabled(not busy)
self.cancel_btn.setVisible(busy)
def _tick(self) -> None:
if self._flow is not None:
self._flow.tick()
self._update()
# ------------------------------------------------------------ actions
def _connect(self) -> None:
if not self.serial_tab.connect_first_box():
QMessageBox.information(self, "Wi-Fi over USB", "No sensorbox found. Check the USB cable (data-capable) "
"and that the box is powered, then try again.")
self._update()
def _clear(self) -> None:
if QMessageBox.question(
self, "Remove Wi-Fi",
"Remove the Wi-Fi network from the box?\n\nThe box restarts and uses Matter again. If it was never "
"paired in Matter, it has no network until you pair it in the Matter app.",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No) == QMessageBox.StandardButton.Yes:
self._run("clear")
def _run(self, action: str) -> None:
if action == "set" and QMessageBox.question(
self, "Write Wi-Fi",
f"Store network '{self.ssid.text()}' on the box?\n\nThe box restarts and connects to this Wi-Fi "
"instead of Matter (about 30 s).",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No) != QMessageBox.StandardButton.Yes:
return
self.steps.clear()
self.result.setVisible(False)
self._flow = WifiFlow(action, self.serial_tab.send_command, self._on_event,
ssid=self.ssid.text(), password=self.password.text())
self._flow.start()
self._update()
def _cancel(self) -> None:
if self._flow is not None:
self._flow.cancel()
self._update()
# ------------------------------------------------------------ events
def _on_line(self, line: LogLine) -> None:
if self._flow is not None:
self._flow.feed(line)
def _on_event(self, ev: FlowEvent) -> None:
mark, colour = MARK[ev.ok]
item = QListWidgetItem(f"{mark} {ev.text}")
item.setForeground(QBrush(QColor(colour)))
self.steps.addItem(item)
self.steps.scrollToBottom()
if self._flow is not None and self._flow.finished or ev.ok is False:
ok = ev.ok is True
border, bg = ("#2e9e44", "#e3f4e7") if ok else ("#d9534f", "#f9e0df")
self.result.setStyleSheet(f"QLabel {{ border:2px solid {border}; background:{bg}; border-radius:6px; }}")
self.result.setText(("<b>Done.</b> " if ok else "<b>Not done.</b> ") + ev.text)
self.result.setVisible(True)
if ok and self._flow and self._flow.info and self._flow.info.ssid and not self.ssid.text():
self.ssid.setText(self._flow.info.ssid) # read: prefill the stored network name
self._update()
+1 -1
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "kota-technician-tool" name = "kota-technician-tool"
version = "0.8.0" version = "0.9.0"
description = "KOTA sensorbox technician diagnostic tool (demo)" description = "KOTA sensorbox technician diagnostic tool (demo)"
requires-python = ">=3.11,<3.14" requires-python = ">=3.11,<3.14"
dependencies = [ dependencies = [
+2 -2
View File
@@ -4,8 +4,8 @@ cd "$(dirname "$0")" || exit 1
# If Finder refuses to open this file (Google Drive drops the executable bit), run it once as: # If Finder refuses to open this file (Google Drive drops the executable bit), run it once as:
# bash run_macos.command (or: chmod +x run_macos.command) # bash run_macos.command (or: chmod +x run_macos.command)
# Keep the virtual environment out of the (Google Drive) tool folder. # One shared Python environment for every version (update_macos.command keeps it current).
export UV_PROJECT_ENVIRONMENT="$HOME/Library/Caches/KotaTechnicianTool/venv-0.8" export UV_PROJECT_ENVIRONMENT="$HOME/Library/Caches/KotaTechnicianTool/venv"
export PATH="$HOME/.local/bin:$PATH" export PATH="$HOME/.local/bin:$PATH"
if ! command -v uv >/dev/null 2>&1; then if ! command -v uv >/dev/null 2>&1; then
+2 -2
View File
@@ -2,8 +2,8 @@
setlocal setlocal
cd /d "%~dp0" cd /d "%~dp0"
rem Keep the virtual environment out of the (Google Drive) tool folder. rem One shared Python environment for every version (update_windows.bat keeps it current).
set "UV_PROJECT_ENVIRONMENT=%LOCALAPPDATA%\KotaTechnicianTool\venv-0.8" set "UV_PROJECT_ENVIRONMENT=%LOCALAPPDATA%\KotaTechnicianTool\venv"
set "PATH=%USERPROFILE%\.local\bin;%PATH%" set "PATH=%USERPROFILE%\.local\bin;%PATH%"
where uv >nul 2>nul where uv >nul 2>nul
@@ -0,0 +1,973 @@
--- connected to COM14 ---
W (9426) wifi:Haven't to connect to a suitable AP now!
--- reset issued by tool ---
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x15 (USB_UART_CHIP_RESET),boot:0xb (SPI_FAST_FLASH_BOOT)
Saved PC:0x4037f366
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce2820,len:0x14f0
load:0x403c8700,len:0xd24
load:0x403cb700,len:0x2f48
entry 0x403c8924
I (24) boot: ESP-IDF v5.5.3-dirty 2nd stage bootloader
I (24) boot: compile time Sep 10 2026 13:24:39
I (25) boot: Multicore bootloader
I (25) boot: chip revision: v0.2
I (28) boot: efuse block revision: v1.4
I (32) boot.esp32s3: Boot SPI Speed : 80MHz
I (35) boot.esp32s3: SPI Mode : DIO
I (39) boot.esp32s3: SPI Flash Size : 8MB
I (43) boot: Enabling RNG early entropy source...
I (48) boot: Partition Table:
I (50) boot: ## Label Usage Type ST Offset Length
I (56) boot: 0 esp_secure_cert unknown 3f 06 0000d000 00002000
I (63) boot: 1 nvs WiFi data 01 02 00010000 00020000
I (69) boot: 2 nvs_keys NVS keys 01 04 00030000 00001000
I (76) boot: 3 otadata OTA data 01 00 00031000 00002000
I (82) boot: 4 phy_init RF data 01 01 00033000 00001000
I (89) boot: 5 ota_0 OTA app 00 10 00040000 00300000
I (95) boot: 6 ota_1 OTA app 00 11 00340000 00300000
I (102) boot: 7 fctry WiFi data 01 02 00640000 00006000
I (109) boot: End of partition table
I (112) esp_image: segment 0: paddr=00040020 vaddr=3c190020 size=67420h (422944) map
I (194) esp_image: segment 1: paddr=000a7448 vaddr=3fc9c700 size=05d00h ( 23808) load
I (200) esp_image: segment 2: paddr=000ad150 vaddr=40374000 size=02ec8h ( 11976) load
I (203) esp_image: segment 3: paddr=000b0020 vaddr=42000020 size=187370h (1602416) map
I (488) esp_image: segment 4: paddr=00237398 vaddr=40376ec8 size=1580ch ( 88076) load
I (507) esp_image: segment 5: paddr=0024cbac vaddr=5000002c size=00020h ( 32) load
I (517) boot: Loaded app from partition at offset 0x40000
I (518) boot: Disabling RNG early entropy source...
I (528) octal_psram: vendor id : 0x0d (AP)
I (528) octal_psram: dev id : 0x02 (generation 3)
I (529) octal_psram: density : 0x03 (64 Mbit)
I (530) octal_psram: good-die : 0x01 (Pass)
I (535) octal_psram: Latency : 0x01 (Fixed)
I (539) octal_psram: VCC : 0x01 (3V)
I (543) octal_psram: SRF : 0x01 (Fast Refresh)
I (548) octal_psram: BurstType : 0x01 (Hybrid Wrap)
I (553) octal_psram: BurstLen : 0x01 (32 Byte)
I (557) octal_psram: Readlatency : 0x02 (10 cycles@Fixed)
I (562) octal_psram: DriveStrength: 0x00 (1/1)
I (567) esp_psram: Found 8MB PSRAM device
I (570) esp_psram: Speed: 40MHz
I (573) cpu_start: Multicore app
I (1307) esp_psram: SPI SRAM memory test OK
I (1315) cpu_start: GPIO 44 and 43 are used as console UART I/O pins
I (1316) cpu_start: Pro cpu start user code
I (1316) cpu_start: cpu freq: 160000000 Hz
I (1318) app_init: Application information:
I (1322) app_init: Project name: kota-sensorboard
I (1327) app_init: App version: 1.0.16
I (1331) app_init: Compile time: Sep 28 2026 15:07:57
I (1336) app_init: ELF file SHA256: 3ae273ec1...
I (1340) app_init: ESP-IDF: v5.5.3-dirty
I (1345) efuse_init: Min chip rev: v0.0
I (1348) efuse_init: Max chip rev: v0.99
I (1353) efuse_init: Chip rev: v0.2
I (1357) heap_init: Initializing. RAM available for dynamic allocation:
I (1363) heap_init: At 3FCB4AD0 len 00034C40 (211 KiB): RAM
I (1368) heap_init: At 3FCE9710 len 00005724 (21 KiB): RAM
I (1373) heap_init: At 3FCF0000 len 00008000 (32 KiB): DRAM
I (1379) heap_init: At 600FE000 len 00001FE8 (7 KiB): RTCRAM
I (1384) esp_psram: Adding pool of 8192K of PSRAM memory to heap allocator
I (1392) spi_flash: detected chip: generic
I (1394) spi_flash: flash io: dio
I (1400) sleep_gpio: Configure to isolate all GPIO pins in sleep state
I (1404) sleep_gpio: Enable automatic switching of GPIO sleep configuration
I (1419) main_task: Started on CPU0
I (1422) esp_psram: Reserving pool of 32K of internal memory for DMA/internal allocations
I (1430) main_task: Calling app_main()
E (1433) ID: [E-MAIN-04] Device MAC address: 14:C1:9F:57:72:48
I (1475) KOTA: led color=green pattern=solid
I (1676) I2C: Creating I2C mutex
I (1694) KOTA: i2c SDA=1 SCL=1 0x39=AS7341 0x68=DS1307 0x6B=SEN66 0x76=BME688
I (1696) OTA_CLIENT: OTA token loaded from NVS: <REDACTED>
I (1698) OTA_CLIENT: Device is not in selfcheck mode
I (1702) OTA_CLIENT: Update metadata loaded from NVS: version=15, status=2
I (1707) OTA_CLIENT: Device is in factory state
I (1711) SPI: Creating SPI mutex
I (1755) SD_CARD: SD card mounted successfully
I (1756) SD_CARD: /sdcard exists, SD card initialized successfully
I (1758) INFLUX_BUFFER: Buffer file does not exist, returning count of 0
I (1763) KOTA: sd type=SDHC size=29.2GB fs=FAT32 free=29.1GB env_keys=INFLUX_TOKEN,INFLUX_URL buffer_lines=0
I (1774) WIFI_CREDENTIALS: SSID/PASSWORD not set in .env; Matter will be used for WiFi provisioning
I (1785) MAIN: Matter node created successfully
W (1787) data_model: Server Cluster 0x00000003 on endpoint 0x0001 already exists. Not creating again.
W (1793) data_model: Attribute 0x0000FFFC on cluster 0x00000003 already exists. Not creating again.
W (1802) data_model: Attribute 0x0000FFFD on cluster 0x00000003 already exists. Not creating again.
W (1811) data_model: Attribute 0x00000000 on cluster 0x00000003 already exists. Not creating again.
W (1819) data_model: Attribute 0x00000001 on cluster 0x00000003 already exists. Not creating again.
W (1828) data_model: Command 0x00000000 on cluster 0x00000003 already exists. Not creating again.
W (1837) data_model: Server Cluster 0x00000003 on endpoint 0x0001 already exists. Not creating again.
W (1846) data_model: Attribute 0x0000FFFC on cluster 0x00000003 already exists. Not creating again.
W (1854) data_model: Attribute 0x0000FFFD on cluster 0x00000003 already exists. Not creating again.
W (1863) data_model: Attribute 0x00000000 on cluster 0x00000003 already exists. Not creating again.
W (1872) data_model: Attribute 0x00000001 on cluster 0x00000003 already exists. Not creating again.
W (1881) data_model: Command 0x00000000 on cluster 0x00000003 already exists. Not creating again.
W (1890) data_model: Server Cluster 0x00000003 on endpoint 0x0001 already exists. Not creating again.
W (1898) data_model: Attribute 0x0000FFFC on cluster 0x00000003 already exists. Not creating again.
W (1907) data_model: Attribute 0x0000FFFD on cluster 0x00000003 already exists. Not creating again.
W (1916) data_model: Attribute 0x00000000 on cluster 0x00000003 already exists. Not creating again.
W (1925) data_model: Attribute 0x00000001 on cluster 0x00000003 already exists. Not creating again.
W (1933) data_model: Command 0x00000000 on cluster 0x00000003 already exists. Not creating again.
I (1944) pp: pp rom version: e7ae62f
I (1945) net80211: net80211 rom version: e7ae62f
I (1951) wifi:wifi driver task: 3fcc9610, prio:23, stack:6656, core=0
I (1969) wifi:wifi firmware version: 4df78f2
I (1970) wifi:wifi certification version: v7.0
I (1971) wifi:config NVS flash: enabled
I (1971) wifi:config nano formatting: disabled
I (1975) wifi:Init data frame dynamic rx buffer num: 32
I (1980) wifi:Init static rx mgmt buffer num: 5
I (1984) wifi:Init management short buffer num: 32
I (1988) wifi:Init dynamic tx buffer num: 32
I (1992) wifi:Init static tx FG buffer num: 2
I (1997) wifi:Init static rx buffer size: 1600
I (2001) wifi:Init static rx buffer num: 10
I (2004) wifi:Init dynamic rx buffer num: 32
I (2009) wifi_init: rx ba win: 6
I (2011) wifi_init: accept mbox: 6
I (2014) wifi_init: tcpip mbox: 32
I (2018) wifi_init: udp mbox: 6
I (2020) wifi_init: tcp mbox: 6
I (2023) wifi_init: tcp tx win: 5760
I (2027) wifi_init: tcp rx win: 5760
I (2030) wifi_init: tcp mss: 1440
I (2045) chip[DL]: NVS set: chip-counters/reboot-count = 13 (0xD)
I (2048) chip[DL]: Real time clock set to 946684800 (2000-01-01 00:00:00 UTC)
I (2050) BLE_INIT: BT controller compile version [1bb2f50]
I (2053) BLE_INIT: Using main XTAL as clock source
I (2058) BLE_INIT: Feature Config, ADV:1, BLE_50:1, DTM:1, SCAN:1, CCA:0, SMP:1, CONNECT:1
I (2067) BLE_INIT: Bluetooth MAC: 14:c1:9f:57:72:4a
I (2072) phy_init: phy_version 711,97bcf0a2,Aug 25 2025,19:04:10
I (2119) NimBLE: GAP procedure initiated: stop advertising.
I (2122) CHIP[DL]: BLE host-controller synced
I (2623) chip[DL]: Starting ESP WiFi layer
I (2626) wifi:mode : sta (14:c1:9f:57:72:48)
I (2627) wifi:enable tsf
W (2628) wifi:Haven't to connect to a suitable AP now!
I (2629) chip[DL]:
I (2629) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 43Attempting to connect WiFi station interface
I (2641) chip[DL]: WiFi station state change: NotConnected -> Connecting
I (2642) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 2
I (2647) chip[DL]:
Done driving station state, nothing else to do...
I (2659) chip[SVR]: Initializing subscription resumption storage...
I (2666) chip[SVR]: Server initializing...
I (2669) chip[TS]: Last Known Good Time: 2026-09-29T14:59:23
I (2674) chip[DMG]: AccessControl: initializing
I (2678) chip[DMG]: Examples::AccessControlDelegate::Init
I (2683) chip[DMG]: AccessControl: setting
I (2687) chip[DMG]: DefaultAclStorage: initializing
I (2691) chip[DMG]: DefaultAclStorage: 0 entries loaded
I (2696) chip[SVR]: WARNING: mTestEventTriggerDelegate is null
I (2715) chip[ZCL]: Using ZAP configuration...
I (2716) esp_matter_cluster: Cluster plugin init common callback
I (2718) chip[DMG]: AccessControlCluster: initializing
I (2720) chip[ZCL]: WRITE ERR: ep 0 clus 0x0000_0030 attr 0x0000_0000 not supported
I (2730) chip[DIS]: Updating services using commissioning mode 1
I (2733) chip[DIS]: CHIP minimal mDNS started advertising.
I (2739) chip[DIS]: Advertise commission parameter vendorID=65521 productID=32768 discriminator=3840/15 cm=1 cp=0
I (2749) chip[DIS]: CHIP minimal mDNS configured as 'Commissionable node device'; instance name: 995B80B34BC8AAD9.
I (2758) chip[DIS]: mDNS service published: _matterc._udp
I (2763) chip[IN]: CASE Server enabling CASE session setups
I (2769) chip[SVR]: Joining Multicast groups
I (2772) chip[SVR]: Server Listening...
I (2778) esp_matter_attribute: ********** R : Endpoint 0x0000's Cluster 0x0000003C's Attribute 0x0000FFFC is 0 **********
I (2788) data_model: Dynamic endpoint 0 added
E (2790) data_model: Cluster cannot be NULL.
I (2795) esp_matter_attribute: ********** R : Endpoint 0x0001's Cluster 0x00000003's Attribute 0x00000001 is 2 **********
I (2806) data_model: Dynamic endpoint 1 added
E (2809) data_model: Cluster cannot be NULL.
I (2815) chip[DL]:
I (2815) MAIN: ESP-Matter started successfully
WIFI_EVENT_STA_START
W (2821) wifi:Haven't to connect to a suitable AP now!
I (2826) chip[DL]: Attempting to connect WiFi station interface
E (2832) wifi:sta is connecting, return error
E (2836) chip[DL]: esp_wifi_connect() failed: ESP_ERR_WIFI_CONN
I (2842) KOTA: boot fw=1.0.16 build=3ae273ec hw=2 mac=14C19F577248 reset=USB_UART_CHIP_RESET mode=matter commissioned=0 last_restart=none
I (2843) chip[DL]: Configuring CHIPoBLE advertising (interval 25 ms, connectable)
I (2861) NimBLE: GAP procedure initiated: advertise;
I (2865) NimBLE: disc_mode=2
I (2867) NimBLE: adv_channel_map=0 own_addr_type=1 adv_filter_policy=0 adv_itvl_min=40 adv_itvl_max=40
I (2877) NimBLE:
I (2880) chip[DL]: CHIPoBLE advertising started
I (2883) MAIN: Commissioning window opened
I (2888) KOTA: matter fabrics=0 window=open qr=MT:Y.K9042C00KA0648G00 manual=34970112332
I (2896) KOTA: led color=cyan pattern=breathe period=3000ms
I (2901) KOTA: matter fabrics=0 window=open qr=MT:Y.K9042C00KA0648G00 manual=34970112332
W (2909) wifi:Haven't to connect to a suitable AP now!
I (2908) KOTA: health up=1s status=OK wifi=disconnected rssi=0 time_valid=0 sd=ok buffer=0 heap=117491 psram=7.9M last_upload=never ota=registered
W (3401) wifi:Haven't to connect to a suitable AP now!
I (3910) KOTA: rtc running=0 time=2000-01-01T00:00:00
W (4402) wifi:Haven't to connect to a suitable AP now!
W (5403) wifi:Haven't to connect to a suitable AP now!
W (6404) wifi:Haven't to connect to a suitable AP now!
I (7219) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (7222) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (7223) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (7226) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
W (7233) wifi:Haven't to connect to a suitable AP now!
E (7238) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (7248) wifi:Haven't to connect to a suitable AP now!
I (7252) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
W (7259) wifi:Haven't to connect to a suitable AP now!
E (7264) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (7273) chip[DL]: Next WiFi station reconnect in 100 ms
I (7278) chip[DL]: Done driving station state, nothing else to do...
W (7379) wifi:Haven't to connect to a suitable AP now!
I (7380) chip[DL]: Attempting to connect WiFi station interface
I (7383) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (7386) wifi:Haven't to connect to a suitable AP now!
E (7391) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (7400) chip[DL]: Done driving station state, nothing else to do...
W (7405) wifi:Haven't to connect to a suitable AP now!
W (8411) wifi:Haven't to connect to a suitable AP now!
W (9415) wifi:Haven't to connect to a suitable AP now!
W (10417) wifi:Haven't to connect to a suitable AP now!
W (11419) wifi:Haven't to connect to a suitable AP now!
I (12201) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (12204) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (12205) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (12208) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
W (12215) wifi:Haven't to connect to a suitable AP now!
E (12220) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (12230) wifi:Haven't to connect to a suitable AP now!
I (12234) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
W (12242) wifi:Haven't to connect to a suitable AP now!
E (12247) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (12256) chip[DL]: Next WiFi station reconnect in 100 ms
I (12261) chip[DL]: Done driving station state, nothing else to do...
W (12361) wifi:Haven't to connect to a suitable AP now!
I (12362) chip[DL]: Attempting to connect WiFi station interface
I (12366) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (12368) wifi:Haven't to connect to a suitable AP now!
E (12373) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (12383) chip[DL]: Done driving station state, nothing else to do...
W (12427) wifi:Haven't to connect to a suitable AP now!
W (13428) wifi:Haven't to connect to a suitable AP now!
I (13912) INFLUX_BUFFER: Read INFLUX_URL from .env file: https://influx.kota-app.com/api/v2/write?bucket=sensorbox&org=kota
I (13917) INFLUX_BUFFER: Buffer file does not exist, returning count of 0
W (13920) INFLUX: Initializing Influx client with URL: https://influx.kota-app.com/api/v2/write?bucket=sensorbox&org=kota
I (13943) BME688: Delaying for 10000 microseconds
W (14430) wifi:Haven't to connect to a suitable AP now!
I (14563) KOTA: mic enabled=1 (GPIO3=0, expected 0)
I (14566) Flicker: Flicker sensor initialized on pin 14
I (14567) temperature_sensor: Range [20°C ~ 100°C], error < 2°C
I (14569) SENSOR_GATHERER: Resumed 2 tasks to gather sensor data
W (14573) wifi:
I (14569) SENSOR_GATHERER: Resumed 4 tasks to gather sensor data
Haven't to connect to a suitable AP now!
I (14570) SEN66: Creating sensor mutex
I (14572) Flicker: Collecting 1024 samples at 1000 Hz for dominant frequency analysis for total measurement window of 1000 ms
I (14600) Flicker: Starting to collect samples in gather task
I (14585) DeviceStatus: Active tasks: 27
I (14588) SEN66: Waking up sensor by setting power GPIO to enabled level...
I (14570) INFLUX_BUFFER: Buffer file does not exist, returning empty buffer
I (14622) INFLUX_BUFFER: Buffer is empty, nothing to flush
I (14613) DeviceStatus: Task list:
gather_sensor_t R 1 1920 25
gather_sensor_t X 1 1368 23
IDLE1 R 0 700 6
IDLE0 R 0 692 5
gather_sensor_t B 1 2556 22
reset_task B 0 3356 10
ds1307_update B 1 776 18
tiT B 18 2420 12
gather_task B 1 1916 20
gather_task B 1 14288 21
ota_task B 1 7516 19
CHIP B 1 3700 14
health B 1 728 17
Tmr Svc B 1 1364 7
led_task B 5 868 8
nimble_host B 21 1348 16
ipc0 S 24 372 1
ipc1 S 24 524 2
sys_evt B 20 2676 11
gather_sensor_t B 1 3180 26
esp_timer S 22 3044 3
gather_sensor_t B 1 2324 24
main B 1 892 4
gather_sensor_t S 1 1480 27
wifi B 23 3796 13
btController B 23 1864 15
flicker_gather_ S 24 1988 28
usb_console B 1 2840 9
W (14702) DeviceStatus: RTC is uninitialized, using current time as timestamp
W (15433) wifi:Haven't to connect to a suitable AP now!
I (15630) Flicker: Finished collecting samples, notifying main task
I (15632) Flicker: Collected 1024 samples for dominant frequency analysis
I (15639) SENSOR_GATHERER: Sensor should now be asleep
W (15650) AS7341: Reading spectral data from AS7341
I (15659) BME688: Delaying for 199517 microseconds
W (15710) DeviceStatus: RTC is uninitialized, using current time as timestamp
W (15958) AS7341: Reading basic counts data from AS7341
W (15974) AS7341: Reading flicker detection state from AS7341
W (16194) as7341: FD Status Register: 0x20 (0b00100000)
I (16201) AS7341: Updating Matter attributes with AS7341 data: 10474
I (16202) esp_matter_attribute: ********** R : Endpoint 0x0001's Cluster 0x00000400's Attribute 0x00000000 is 0 **********
I (16208) esp_matter_attribute: ********** W : Endpoint 0x0001's Cluster 0x00000400's Attribute 0x00000000 is 10474 **********
E (16219) MAIN: [E-MAIN-03] Attribute update callback: endpoint_id: 1, cluster_id: 0x400, attribute_id: 0x0
E (16229) MAIN: [E-MAIN-03] Attribute update callback: endpoint_id: 1, cluster_id: 0x400, attribute_id: 0x0
W (16238) AS7341: RTC is uninitialized, using current time as timestamp
I (16241) esp_matter_attribute: ********** R : Endpoint 0x0001's Cluster 0x00000403's Attribute 0x00000000 is null **********
I (16256) esp_matter_attribute: ********** W : Endpoint 0x0001's Cluster 0x00000403's Attribute 0x00000000 is 1021 **********
E (16267) MAIN: [E-MAIN-03] Attribute update callback: endpoint_id: 1, cluster_id: 0x403, attribute_id: 0x0
E (16276) MAIN: [E-MAIN-03] Attribute update callback: endpoint_id: 1, cluster_id: 0x403, attribute_id: 0x0
W (16286) BME688: RTC is uninitialized, using current time as timestamp
W (16434) wifi:Haven't to connect to a suitable AP now!
W (16711) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (17183) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (17186) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (17187) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (17190) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
W (17198) wifi:Haven't to connect to a suitable AP now!
E (17203) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (17212) wifi:Haven't to connect to a suitable AP now!
I (17217) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
W (17224) wifi:Haven't to connect to a suitable AP now!
E (17229) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (17239) chip[DL]: Next WiFi station reconnect in 100 ms
I (17243) chip[DL]: Done driving station state, nothing else to do...
W (17244) AS7341: RTC is uninitialized, using current time as timestamp
W (17291) BME688: RTC is uninitialized, using current time as timestamp
W (17344) wifi:Haven't to connect to a suitable AP now!
I (17346) chip[DL]: Attempting to connect WiFi station interface
I (17349) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (17351) wifi:Haven't to connect to a suitable AP now!
E (17356) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (17366) chip[DL]: Done driving station state, nothing else to do...
W (17437) wifi:Haven't to connect to a suitable AP now!
W (17712) DeviceStatus: RTC is uninitialized, using current time as timestamp
W (18256) AS7341: RTC is uninitialized, using current time as timestamp
W (18292) BME688: RTC is uninitialized, using current time as timestamp
W (18439) wifi:Haven't to connect to a suitable AP now!
W (18713) DeviceStatus: RTC is uninitialized, using current time as timestamp
W (19257) AS7341: RTC is uninitialized, using current time as timestamp
W (19293) BME688: RTC is uninitialized, using current time as timestamp
W (19440) wifi:Haven't to connect to a suitable AP now!
I (19615) SEN66: Sent start measurement command, waiting for sensor to be ready...
W (19714) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (19928) KOTA: cmd ping ok=1 fw=1.0.16 api=1
I (19933) KOTA: cmd wifi_get ok=1 ssid=- password_set=0 mode=matter
W (20258) AS7341: RTC is uninitialized, using current time as timestamp
W (20294) BME688: RTC is uninitialized, using current time as timestamp
W (20441) wifi:Haven't to connect to a suitable AP now!
W (20715) DeviceStatus: RTC is uninitialized, using current time as timestamp
W (21259) AS7341: RTC is uninitialized, using current time as timestamp
W (21295) BME688: RTC is uninitialized, using current time as timestamp
W (21442) wifi:Haven't to connect to a suitable AP now!
W (21716) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (22166) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (22169) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (22170) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (22173) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
W (22181) wifi:Haven't to connect to a suitable AP now!
E (22186) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (22196) wifi:Haven't to connect to a suitable AP now!
I (22200) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
W (22207) wifi:Haven't to connect to a suitable AP now!
E (22212) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (22222) chip[DL]: Next WiFi station reconnect in 100 ms
I (22226) chip[DL]: Done driving station state, nothing else to do...
W (22260) AS7341: RTC is uninitialized, using current time as timestamp
W (22296) BME688: RTC is uninitialized, using current time as timestamp
W (22327) wifi:Haven't to connect to a suitable AP now!
I (22328) chip[DL]: Attempting to connect WiFi station interface
I (22332) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (22334) wifi:Haven't to connect to a suitable AP now!
E (22340) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (22349) chip[DL]: Done driving station state, nothing else to do...
W (22446) wifi:Haven't to connect to a suitable AP now!
I (22574) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (22717) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (23075) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (23261) AS7341: RTC is uninitialized, using current time as timestamp
W (23297) BME688: RTC is uninitialized, using current time as timestamp
W (23447) wifi:Haven't to connect to a suitable AP now!
I (23576) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (23718) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (24077) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (24262) AS7341: RTC is uninitialized, using current time as timestamp
W (24299) BME688: RTC is uninitialized, using current time as timestamp
W (24448) wifi:Haven't to connect to a suitable AP now!
I (24570) OTA_CLIENT: HTTP client handle: 0x3fcf02e4
I (24578) SENSOR_GATHERER: 2/2 tasks still running, waiting...
I (24710) MICROPHONE: Read 600000 bytes in 9940 ms
I (24712) MICROPHONE: Read 600000 bytes of audio data
W (24719) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (25079) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (25264) AS7341: RTC is uninitialized, using current time as timestamp
W (25300) BME688: RTC is uninitialized, using current time as timestamp
W (25449) wifi:Haven't to connect to a suitable AP now!
I (25580) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (25720) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (26081) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (26265) AS7341: RTC is uninitialized, using current time as timestamp
W (26301) BME688: RTC is uninitialized, using current time as timestamp
W (26450) wifi:Haven't to connect to a suitable AP now!
I (26582) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (26721) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (27083) SENSOR_GATHERER: 2/2 tasks still running, waiting...
I (27150) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (27152) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (27154) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (27157) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
W (27164) wifi:Haven't to connect to a suitable AP now!
E (27169) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (27179) wifi:Haven't to connect to a suitable AP now!
I (27183) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
W (27190) wifi:Haven't to connect to a suitable AP now!
E (27196) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (27205) chip[DL]: Next WiFi station reconnect in 100 ms
I (27209) chip[DL]: Done driving station state, nothing else to do...
W (27266) AS7341: RTC is uninitialized, using current time as timestamp
W (27302) BME688: RTC is uninitialized, using current time as timestamp
W (27310) wifi:Haven't to connect to a suitable AP now!
I (27311) chip[DL]: Attempting to connect WiFi station interface
I (27315) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (27318) wifi:Haven't to connect to a suitable AP now!
E (27323) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (27332) chip[DL]: Done driving station state, nothing else to do...
W (27456) wifi:Haven't to connect to a suitable AP now!
I (27584) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (27722) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (28085) SENSOR_GATHERER: 2/2 tasks still running, waiting...
I (28160) MICROPHONE: Raw block stats: mean=-17.8 min=-146018 max=134018
I (28161) MICROPHONE: Sum SQ: 0.578925, RMS pressure: 0.001701, Normalized: 0.001701, dB peak: -55.38
W (28166) SEN66: RTC is uninitialized, using current time as timestamp
W (28267) AS7341: RTC is uninitialized, using current time as timestamp
W (28303) BME688: RTC is uninitialized, using current time as timestamp
W (28457) wifi:Haven't to connect to a suitable AP now!
I (28586) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (28723) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (29087) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (29172) SEN66: RTC is uninitialized, using current time as timestamp
W (29268) AS7341: RTC is uninitialized, using current time as timestamp
W (29304) BME688: RTC is uninitialized, using current time as timestamp
W (29458) wifi:Haven't to connect to a suitable AP now!
I (29588) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (29724) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (30089) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (30173) SEN66: RTC is uninitialized, using current time as timestamp
W (30269) AS7341: RTC is uninitialized, using current time as timestamp
W (30305) BME688: RTC is uninitialized, using current time as timestamp
W (30459) wifi:Haven't to connect to a suitable AP now!
I (30590) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (30725) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (31091) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (31174) SEN66: RTC is uninitialized, using current time as timestamp
W (31270) AS7341: RTC is uninitialized, using current time as timestamp
W (31306) BME688: RTC is uninitialized, using current time as timestamp
W (31460) wifi:Haven't to connect to a suitable AP now!
E (31572) esp-tls: couldn't get hostname for :bin.kota-app.com: getaddrinfo() returns 202, addrinfo=0x0
E (31573) esp-tls: Failed to open new connection
E (31575) transport_base: Failed to open a new connection
E (31580) HTTP_CLIENT: Connection failed, sock < 0
E (31585) OTA_CLIENT: [E-OTA-01] Error ESP_ERR_HTTP_CONNECT at ./main/ota_client.cpp:355
I (31592) SENSOR_GATHERER: 2/2 tasks still running, waiting...
E (31593) OTA_CLIENT: [E-OTA-13] Failed to check for updates: ESP_ERR_HTTP_CONNECT
I (31606) KOTA: status OK -> CONNECTION_ERROR reason=ota_check_failed
W (31726) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (32098) SENSOR_GATHERER: 2/2 tasks still running, waiting...
I (32133) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (32135) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (32137) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (32140) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
W (32147) wifi:Haven't to connect to a suitable AP now!
E (32152) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (32162) wifi:Haven't to connect to a suitable AP now!
I (32166) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
W (32173) wifi:Haven't to connect to a suitable AP now!
W (32175) SEN66: RTC is uninitialized, using current time as timestamp
E (32179) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (32194) chip[DL]: Next WiFi station reconnect in 100 ms
I (32199) chip[DL]: Done driving station state, nothing else to do...
W (32271) AS7341: RTC is uninitialized, using current time as timestamp
W (32300) wifi:Haven't to connect to a suitable AP now!
I (32301) chip[DL]: Attempting to connect WiFi station interface
I (32305) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (32307) BME688: RTC is uninitialized, using current time as timestamp
W (32307) wifi:Haven't to connect to a suitable AP now!
E (32319) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (32328) chip[DL]: Done driving station state, nothing else to do...
W (32462) wifi:Haven't to connect to a suitable AP now!
I (32599) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (32727) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (32730) chip[DL]: bleAdv Timeout : Start slow advertisement
I (32732) chip[DL]: Configuring CHIPoBLE advertising (interval 500 ms, connectable)
I (32737) chip[DL]: Device already advertising, stop active advertisement and restart
I (32744) NimBLE: GAP procedure initiated: stop advertising.
I (32750) NimBLE: GAP procedure initiated: advertise;
I (32754) NimBLE: disc_mode=2
I (32756) NimBLE: adv_channel_map=0 own_addr_type=1 adv_filter_policy=0 adv_itvl_min=800 adv_itvl_max=800
I (32767) NimBLE:
I (33100) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (33184) SEN66: RTC is uninitialized, using current time as timestamp
W (33272) AS7341: RTC is uninitialized, using current time as timestamp
W (33320) BME688: RTC is uninitialized, using current time as timestamp
W (33463) wifi:Haven't to connect to a suitable AP now!
I (33601) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (33728) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (34102) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (34185) SEN66: RTC is uninitialized, using current time as timestamp
W (34274) AS7341: RTC is uninitialized, using current time as timestamp
W (34321) BME688: RTC is uninitialized, using current time as timestamp
W (34464) wifi:Haven't to connect to a suitable AP now!
I (34603) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (34729) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (35104) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (35186) SEN66: RTC is uninitialized, using current time as timestamp
W (35275) AS7341: RTC is uninitialized, using current time as timestamp
W (35322) BME688: RTC is uninitialized, using current time as timestamp
W (35465) wifi:Haven't to connect to a suitable AP now!
I (35605) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (35730) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (36106) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (36187) SEN66: RTC is uninitialized, using current time as timestamp
W (36276) AS7341: RTC is uninitialized, using current time as timestamp
W (36323) BME688: RTC is uninitialized, using current time as timestamp
W (36466) wifi:Haven't to connect to a suitable AP now!
I (36607) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (36731) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (37107) SENSOR_GATHERER: 2/2 tasks still running, waiting...
I (37122) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (37125) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (37126) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (37129) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
W (37137) wifi:Haven't to connect to a suitable AP now!
E (37142) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (37151) wifi:Haven't to connect to a suitable AP now!
I (37156) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
W (37163) wifi:Haven't to connect to a suitable AP now!
E (37168) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (37178) chip[DL]: Next WiFi station reconnect in 100 ms
I (37182) chip[DL]: Done driving station state, nothing else to do...
W (37188) SEN66: RTC is uninitialized, using current time as timestamp
W (37277) AS7341: RTC is uninitialized, using current time as timestamp
W (37283) wifi:Haven't to connect to a suitable AP now!
I (37284) chip[DL]: Attempting to connect WiFi station interface
I (37287) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (37290) wifi:Haven't to connect to a suitable AP now!
E (37295) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (37305) chip[DL]: Done driving station state, nothing else to do...
W (37324) BME688: RTC is uninitialized, using current time as timestamp
W (37468) wifi:Haven't to connect to a suitable AP now!
I (37608) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (37732) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (38109) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (38195) SEN66: RTC is uninitialized, using current time as timestamp
W (38278) AS7341: RTC is uninitialized, using current time as timestamp
W (38325) BME688: RTC is uninitialized, using current time as timestamp
W (38470) wifi:Haven't to connect to a suitable AP now!
I (38610) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (38733) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (39111) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (39196) SEN66: RTC is uninitialized, using current time as timestamp
W (39279) AS7341: RTC is uninitialized, using current time as timestamp
W (39326) BME688: RTC is uninitialized, using current time as timestamp
W (39471) wifi:Haven't to connect to a suitable AP now!
I (39612) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (39736) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (40113) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (40197) SEN66: RTC is uninitialized, using current time as timestamp
W (40280) AS7341: RTC is uninitialized, using current time as timestamp
W (40326) BME688: RTC is uninitialized, using current time as timestamp
W (40473) wifi:Haven't to connect to a suitable AP now!
I (40614) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (40737) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (41115) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (41198) SEN66: RTC is uninitialized, using current time as timestamp
W (41281) AS7341: RTC is uninitialized, using current time as timestamp
W (41327) BME688: RTC is uninitialized, using current time as timestamp
W (41474) wifi:Haven't to connect to a suitable AP now!
I (41616) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (41738) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (42105) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (42108) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (42109) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (42112) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
I (42116) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (42120) wifi:Haven't to connect to a suitable AP now!
E (42130) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (42140) wifi:Haven't to connect to a suitable AP now!
I (42144) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
W (42151) wifi:Haven't to connect to a suitable AP now!
E (42156) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (42166) chip[DL]: Next WiFi station reconnect in 100 ms
I (42170) chip[DL]: Done driving station state, nothing else to do...
W (42199) SEN66: RTC is uninitialized, using current time as timestamp
W (42271) wifi:Haven't to connect to a suitable AP now!
I (42272) chip[DL]: Attempting to connect WiFi station interface
I (42275) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (42278) wifi:Haven't to connect to a suitable AP now!
W (42283) AS7341: RTC is uninitialized, using current time as timestamp
E (42283) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (42299) chip[DL]: Done driving station state, nothing else to do...
W (42328) BME688: RTC is uninitialized, using current time as timestamp
W (42476) wifi:Haven't to connect to a suitable AP now!
I (42625) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (42739) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (43126) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (43200) SEN66: RTC is uninitialized, using current time as timestamp
W (43290) AS7341: RTC is uninitialized, using current time as timestamp
W (43329) BME688: RTC is uninitialized, using current time as timestamp
W (43482) wifi:Haven't to connect to a suitable AP now!
I (43627) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (43740) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (44128) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (44201) SEN66: RTC is uninitialized, using current time as timestamp
W (44291) AS7341: RTC is uninitialized, using current time as timestamp
W (44330) BME688: RTC is uninitialized, using current time as timestamp
W (44486) wifi:Haven't to connect to a suitable AP now!
I (44629) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (44741) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (45130) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (45202) SEN66: RTC is uninitialized, using current time as timestamp
W (45292) AS7341: RTC is uninitialized, using current time as timestamp
W (45331) BME688: RTC is uninitialized, using current time as timestamp
W (45487) wifi:Haven't to connect to a suitable AP now!
I (45631) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (45742) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (46132) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (46203) SEN66: RTC is uninitialized, using current time as timestamp
W (46293) AS7341: RTC is uninitialized, using current time as timestamp
W (46332) BME688: RTC is uninitialized, using current time as timestamp
W (46488) wifi:Haven't to connect to a suitable AP now!
I (46633) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (46743) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (47093) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (47095) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (47097) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (47100) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
W (47107) wifi:Haven't to connect to a suitable AP now!
E (47112) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (47122) wifi:Haven't to connect to a suitable AP now!
I (47126) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
I (47134) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (47134) wifi:Haven't to connect to a suitable AP now!
E (47144) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (47154) chip[DL]: Next WiFi station reconnect in 100 ms
I (47158) chip[DL]: Done driving station state, nothing else to do...
W (47204) SEN66: RTC is uninitialized, using current time as timestamp
W (47259) wifi:Haven't to connect to a suitable AP now!
I (47260) chip[DL]: Attempting to connect WiFi station interface
I (47263) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (47266) wifi:Haven't to connect to a suitable AP now!
E (47271) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (47281) chip[DL]: Done driving station state, nothing else to do...
W (47294) AS7341: RTC is uninitialized, using current time as timestamp
W (47333) BME688: RTC is uninitialized, using current time as timestamp
W (47493) wifi:Haven't to connect to a suitable AP now!
I (47639) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (47744) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (48140) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (48205) SEN66: RTC is uninitialized, using current time as timestamp
W (48295) AS7341: RTC is uninitialized, using current time as timestamp
W (48334) BME688: RTC is uninitialized, using current time as timestamp
W (48495) wifi:Haven't to connect to a suitable AP now!
I (48641) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (48747) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (49142) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (49206) SEN66: RTC is uninitialized, using current time as timestamp
W (49296) AS7341: RTC is uninitialized, using current time as timestamp
W (49335) BME688: RTC is uninitialized, using current time as timestamp
W (49496) wifi:Haven't to connect to a suitable AP now!
I (49643) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (49748) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (50144) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (50207) SEN66: RTC is uninitialized, using current time as timestamp
W (50297) AS7341: RTC is uninitialized, using current time as timestamp
W (50336) BME688: RTC is uninitialized, using current time as timestamp
W (50498) wifi:Haven't to connect to a suitable AP now!
I (50645) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (50749) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (51146) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (51208) SEN66: RTC is uninitialized, using current time as timestamp
W (51298) AS7341: RTC is uninitialized, using current time as timestamp
W (51337) BME688: RTC is uninitialized, using current time as timestamp
W (51500) wifi:Haven't to connect to a suitable AP now!
I (51647) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (51750) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (52081) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (52084) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (52085) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (52088) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
W (52096) wifi:Haven't to connect to a suitable AP now!
E (52100) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (52110) wifi:Haven't to connect to a suitable AP now!
I (52115) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
W (52122) wifi:Haven't to connect to a suitable AP now!
E (52127) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (52136) chip[DL]: Next WiFi station reconnect in 100 ms
I (52141) chip[DL]: Done driving station state, nothing else to do...
I (52148) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (52209) SEN66: RTC is uninitialized, using current time as timestamp
W (52242) wifi:Haven't to connect to a suitable AP now!
I (52243) chip[DL]: Attempting to connect WiFi station interface
I (52246) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (52249) wifi:Haven't to connect to a suitable AP now!
E (52254) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (52264) chip[DL]: Done driving station state, nothing else to do...
W (52299) AS7341: RTC is uninitialized, using current time as timestamp
W (52338) BME688: RTC is uninitialized, using current time as timestamp
W (52508) wifi:Haven't to connect to a suitable AP now!
I (52653) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (52751) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (53154) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (53210) SEN66: RTC is uninitialized, using current time as timestamp
W (53300) AS7341: RTC is uninitialized, using current time as timestamp
W (53339) BME688: RTC is uninitialized, using current time as timestamp
W (53509) wifi:Haven't to connect to a suitable AP now!
I (53655) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (53752) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (54156) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (54212) SEN66: RTC is uninitialized, using current time as timestamp
W (54301) AS7341: RTC is uninitialized, using current time as timestamp
W (54340) BME688: RTC is uninitialized, using current time as timestamp
W (54510) wifi:Haven't to connect to a suitable AP now!
I (54657) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (54753) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (55158) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (55213) SEN66: RTC is uninitialized, using current time as timestamp
W (55302) AS7341: RTC is uninitialized, using current time as timestamp
W (55341) BME688: RTC is uninitialized, using current time as timestamp
W (55511) wifi:Haven't to connect to a suitable AP now!
I (55659) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (55754) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (56160) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (56214) SEN66: RTC is uninitialized, using current time as timestamp
W (56303) AS7341: RTC is uninitialized, using current time as timestamp
W (56342) BME688: RTC is uninitialized, using current time as timestamp
W (56512) wifi:Haven't to connect to a suitable AP now!
I (56661) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (56755) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (57064) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (57067) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (57068) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (57071) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
W (57079) wifi:Haven't to connect to a suitable AP now!
E (57083) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (57093) wifi:Haven't to connect to a suitable AP now!
I (57097) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
W (57105) wifi:Haven't to connect to a suitable AP now!
E (57110) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (57119) chip[DL]: Next WiFi station reconnect in 100 ms
I (57124) chip[DL]: Done driving station state, nothing else to do...
I (57162) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (57215) SEN66: RTC is uninitialized, using current time as timestamp
W (57225) wifi:Haven't to connect to a suitable AP now!
I (57226) chip[DL]: Attempting to connect WiFi station interface
I (57230) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (57232) wifi:Haven't to connect to a suitable AP now!
E (57237) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (57247) chip[DL]: Done driving station state, nothing else to do...
W (57304) AS7341: RTC is uninitialized, using current time as timestamp
W (57344) BME688: RTC is uninitialized, using current time as timestamp
W (57517) wifi:Haven't to connect to a suitable AP now!
I (57663) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (57756) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (58164) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (58216) SEN66: RTC is uninitialized, using current time as timestamp
W (58305) AS7341: RTC is uninitialized, using current time as timestamp
W (58345) BME688: RTC is uninitialized, using current time as timestamp
W (58518) wifi:Haven't to connect to a suitable AP now!
I (58665) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (58757) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (59166) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (59217) SEN66: RTC is uninitialized, using current time as timestamp
W (59306) AS7341: RTC is uninitialized, using current time as timestamp
W (59346) BME688: RTC is uninitialized, using current time as timestamp
W (59519) wifi:Haven't to connect to a suitable AP now!
I (59667) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (59758) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (60168) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (60218) SEN66: RTC is uninitialized, using current time as timestamp
W (60307) AS7341: RTC is uninitialized, using current time as timestamp
W (60346) BME688: RTC is uninitialized, using current time as timestamp
W (60520) wifi:Haven't to connect to a suitable AP now!
I (60669) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (60759) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (61170) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (61219) SEN66: RTC is uninitialized, using current time as timestamp
W (61308) AS7341: RTC is uninitialized, using current time as timestamp
W (61347) BME688: RTC is uninitialized, using current time as timestamp
W (61521) wifi:Haven't to connect to a suitable AP now!
I (61671) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (61760) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (62047) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (62050) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (62051) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (62054) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
W (62062) wifi:Haven't to connect to a suitable AP now!
E (62067) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (62076) wifi:Haven't to connect to a suitable AP now!
I (62081) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
W (62088) wifi:Haven't to connect to a suitable AP now!
E (62093) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (62102) chip[DL]: Next WiFi station reconnect in 100 ms
I (62107) chip[DL]: Done driving station state, nothing else to do...
I (62172) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (62208) wifi:Haven't to connect to a suitable AP now!
I (62209) chip[DL]: Attempting to connect WiFi station interface
I (62212) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (62215) wifi:Haven't to connect to a suitable AP now!
W (62220) SEN66: RTC is uninitialized, using current time as timestamp
E (62220) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (62236) chip[DL]: Done driving station state, nothing else to do...
W (62309) AS7341: RTC is uninitialized, using current time as timestamp
W (62348) BME688: RTC is uninitialized, using current time as timestamp
W (62527) wifi:Haven't to connect to a suitable AP now!
I (62673) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (62761) DeviceStatus: RTC is uninitialized, using current time as timestamp
W (62925) wifi:Haven't to connect to a suitable AP now!
I (62925) KOTA: health up=61s status=CONNECTION_ERROR wifi=disconnected rssi=0 time_valid=0 sd=ok buffer=0 heap=47259 psram=7.3M last_upload=never ota=registered
I (63174) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (63227) SEN66: RTC is uninitialized, using current time as timestamp
W (63310) AS7341: RTC is uninitialized, using current time as timestamp
W (63349) BME688: RTC is uninitialized, using current time as timestamp
W (63528) wifi:Haven't to connect to a suitable AP now!
I (63675) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (63762) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (64176) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (64228) SEN66: RTC is uninitialized, using current time as timestamp
W (64311) AS7341: RTC is uninitialized, using current time as timestamp
W (64350) BME688: RTC is uninitialized, using current time as timestamp
W (64529) wifi:Haven't to connect to a suitable AP now!
I (64617) SEN66: First measurement, waiting additional 120 seconds for sensor to stabilize...
I (64677) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (64763) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (65178) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (65229) SEN66: RTC is uninitialized, using current time as timestamp
W (65312) AS7341: RTC is uninitialized, using current time as timestamp
W (65351) BME688: RTC is uninitialized, using current time as timestamp
W (65530) wifi:Haven't to connect to a suitable AP now!
I (65679) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (65764) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (66180) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (66230) SEN66: RTC is uninitialized, using current time as timestamp
W (66313) AS7341: RTC is uninitialized, using current time as timestamp
W (66352) BME688: RTC is uninitialized, using current time as timestamp
W (66531) wifi:Haven't to connect to a suitable AP now!
I (66681) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (66765) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (67030) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (67033) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (67034) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (67037) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
W (67045) wifi:Haven't to connect to a suitable AP now!
E (67049) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (67059) wifi:Haven't to connect to a suitable AP now!
I (67063) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
W (67071) wifi:Haven't to connect to a suitable AP now!
E (67076) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (67085) chip[DL]: Next WiFi station reconnect in 100 ms
I (67090) chip[DL]: Done driving station state, nothing else to do...
I (67182) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (67191) wifi:Haven't to connect to a suitable AP now!
I (67192) chip[DL]: Attempting to connect WiFi station interface
I (67195) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (67198) wifi:Haven't to connect to a suitable AP now!
E (67203) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (67213) chip[DL]: Done driving station state, nothing else to do...
W (67231) SEN66: RTC is uninitialized, using current time as timestamp
W (67314) AS7341: RTC is uninitialized, using current time as timestamp
W (67353) BME688: RTC is uninitialized, using current time as timestamp
W (67537) wifi:Haven't to connect to a suitable AP now!
I (67683) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (67766) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (68184) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (68232) SEN66: RTC is uninitialized, using current time as timestamp
W (68315) AS7341: RTC is uninitialized, using current time as timestamp
W (68354) BME688: RTC is uninitialized, using current time as timestamp
W (68542) wifi:Haven't to connect to a suitable AP now!
I (68685) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (68767) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (69186) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (69233) SEN66: RTC is uninitialized, using current time as timestamp
W (69316) AS7341: RTC is uninitialized, using current time as timestamp
W (69355) BME688: RTC is uninitialized, using current time as timestamp
W (69546) wifi:Haven't to connect to a suitable AP now!
I (69687) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (69768) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (70188) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (70234) SEN66: RTC is uninitialized, using current time as timestamp
W (70317) AS7341: RTC is uninitialized, using current time as timestamp
W (70356) BME688: RTC is uninitialized, using current time as timestamp
W (70547) wifi:Haven't to connect to a suitable AP now!
I (70689) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (70769) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (71190) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (71235) SEN66: RTC is uninitialized, using current time as timestamp
W (71318) AS7341: RTC is uninitialized, using current time as timestamp
W (71357) BME688: RTC is uninitialized, using current time as timestamp
W (71548) wifi:Haven't to connect to a suitable AP now!
I (71691) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (71770) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (72013) wifi:Coexist: Wi-Fi connect fail, apply reconnect coex policy
I (72015) chip[DL]: Posting ESPSystemEvent: Wifi Event with eventId : 5
I (72017) chip[DL]: WIFI_EVENT_STA_DISCONNECTED
I (72020) chip[DL]: WiFi station state change: Connecting -> Connecting_Failed
W (72027) wifi:Haven't to connect to a suitable AP now!
E (72032) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
W (72042) wifi:Haven't to connect to a suitable AP now!
I (72046) chip[DL]: WiFi station state change: Connecting_Failed -> NotConnected
W (72054) wifi:Haven't to connect to a suitable AP now!
E (72059) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (72068) chip[DL]: Next WiFi station reconnect in 100 ms
I (72073) chip[DL]: Done driving station state, nothing else to do...
W (72173) wifi:Haven't to connect to a suitable AP now!
I (72175) chip[DL]: Attempting to connect WiFi station interface
I (72178) chip[DL]: WiFi station state change: NotConnected -> Connecting
W (72181) wifi:Haven't to connect to a suitable AP now!
E (72185) chip[DL]: Failed to get configured network when updating network status: Error ESP32:0x0500300F
I (72191) SENSOR_GATHERER: 2/2 tasks still running, waiting...
I (72195) chip[DL]: Done driving station state, nothing else to do...
W (72236) SEN66: RTC is uninitialized, using current time as timestamp
W (72319) AS7341: RTC is uninitialized, using current time as timestamp
W (72358) BME688: RTC is uninitialized, using current time as timestamp
W (72552) wifi:Haven't to connect to a suitable AP now!
I (72700) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (72771) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (73201) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (73237) SEN66: RTC is uninitialized, using current time as timestamp
W (73320) AS7341: RTC is uninitialized, using current time as timestamp
W (73359) BME688: RTC is uninitialized, using current time as timestamp
W (73553) wifi:Haven't to connect to a suitable AP now!
I (73702) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (73772) DeviceStatus: RTC is uninitialized, using current time as timestamp
I (74203) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (74238) SEN66: RTC is uninitialized, using current time as timestamp
W (74321) AS7341: RTC is uninitialized, using current time as timestamp
W (74360) BME688: RTC is uninitialized, using current time as timestamp
W (74555) wifi:Haven't to connect to a suitable AP now!
I (74581) SENSOR_GATHERER: 3/4 tasks still running, waiting...
I (74627) INFLUX_BUFFER: Buffer file does not exist, returning empty buffer
I (74628) INFLUX_BUFFER: Buffer is empty, nothing to flush
I (74704) SENSOR_GATHERER: 2/2 tasks still running, waiting...
W (74773) DeviceStatus: RTC is uninitialized, using current time as timestamp
--- disconnected ---
+177
View File
@@ -0,0 +1,177 @@
"""Wi-Fi over USB (firmware usb_console api=1): encoding, replies and the whole
write/clear/read job, driven with reply lines in the firmware's exact format."""
import pytest
from kota_tech.core.logline import parse_line
from kota_tech.diag.engine import DiagnosticsEngine
from kota_tech.serialio.commands import (
CONNECT_TIMEOUT_S, PING_TIMEOUT_S, Step, WifiFlow, loggable, parse_reply, validate_wifi, wifi_set_command)
PING = "I (5000) KOTA: cmd ping ok=1 fw=1.0.16 api=1"
BOOT = ("I (2843) KOTA: boot fw=1.0.16 build=3ae273ec hw=2 mac=A4CB8FC946F8 reset=RTC_SW_SYS_RST "
"mode={mode} commissioned=- last_restart={last}")
HEALTH = ("I (9000) KOTA: cmd health ok=1 up=9s status=OK wifi={wifi} rssi={rssi} time_valid=1 sd=ok buffer=0 "
"heap=90000 psram=7.6M last_upload=never ota=registered")
class Clock:
def __init__(self):
self.t = 0.0
def __call__(self):
return self.t
def make(action, **kw):
sent, events, clock = [], [], Clock()
flow = WifiFlow(action, lambda c: sent.append(c) or True, events.append, now=clock, **kw)
return flow, sent, events, clock
def feed(flow, text):
flow.feed(parse_line(text))
# ------------------------------------------------------------- encoding
def test_wifi_set_command_is_hex_utf8():
assert wifi_set_command("Biuro 2.4", "tajne=haslo1") == \
"kota wifi set 426975726f20322e34 74616a6e653d6861736c6f31"
assert wifi_set_command("Łąka", "zażółć1234").split()[3] == "c581c4856b61"
@pytest.mark.parametrize("ssid,password,problem", [
("", "12345678", "network name"),
("x" * 33, "12345678", "32 bytes"),
("net", "1234567", "8-63"),
("net", "x" * 64, "8-63"),
("net\n", "12345678", "line break"),
])
def test_validation_matches_firmware_limits(ssid, password, problem):
assert any(problem in p for p in validate_wifi(ssid, password))
with pytest.raises(ValueError):
wifi_set_command(ssid, password)
def test_password_never_logged():
cmd = wifi_set_command("Biuro", "sekretne-haslo")
assert "sekretne" not in loggable(cmd) and "7365" not in loggable(cmd)
assert "Biuro" in loggable(cmd)
def test_reply_parsing():
r = parse_reply(parse_line("I (1) KOTA: cmd wifi_set ok=0 err=password_length"))
assert r.name == "wifi_set" and not r.ok and "8-63" in r.error
assert parse_reply(parse_line("I (1) KOTA: health up=1s")) is None
# ----------------------------------------------------------------- flows
def test_write_wifi_happy_path():
flow, sent, events, clock = make("set", ssid="Biuro", password="haslo1234")
flow.start()
assert sent == ["kota ping"]
feed(flow, PING)
assert sent[-1] == wifi_set_command("Biuro", "haslo1234") and flow.step == Step.SEND
feed(flow, "I (5100) KOTA: cmd wifi_set ok=1 restart=1")
assert flow.step == Step.RESTART
feed(flow, "W (5101) KOTA: restart reason=usb_wifi_set")
feed(flow, BOOT.format(mode="wifi", last="usb_wifi_set"))
assert flow.step == Step.CONNECT
clock.t += 6
flow.tick()
assert sent[-1] == "kota health"
feed(flow, HEALTH.format(wifi="disconnected", rssi=0))
assert flow.step == Step.CONNECT
feed(flow, HEALTH.format(wifi="connected", rssi=-58))
assert flow.step == Step.DONE and "Connected to 'Biuro'" in events[-1].text and "-58" in events[-1].text
def test_old_firmware_without_console_times_out_on_ping():
flow, sent, events, clock = make("read")
flow.start()
clock.t += PING_TIMEOUT_S + 0.1
flow.tick()
assert flow.step == Step.FAILED and "USB console" in events[-1].text
def test_box_rejects_settings():
flow, sent, events, _ = make("set", ssid="Biuro", password="haslo1234")
flow.start()
feed(flow, PING)
feed(flow, "I (5100) KOTA: cmd wifi_set ok=0 err=sd_not_mounted")
assert flow.step == Step.FAILED and "SD card" in events[-1].text
def test_wrong_password_does_not_connect():
flow, _, events, clock = make("set", ssid="Biuro", password="zlehaslo1")
flow.start()
feed(flow, PING)
feed(flow, "I (5100) KOTA: cmd wifi_set ok=1 restart=1")
feed(flow, BOOT.format(mode="wifi", last="usb_wifi_set"))
clock.t += CONNECT_TIMEOUT_S + 1
flow.tick()
assert flow.step == Step.FAILED and "2.4 GHz" in events[-1].text
def test_clear_returns_to_matter():
flow, sent, events, _ = make("clear")
flow.start()
feed(flow, PING)
assert sent[-1] == "kota wifi clear"
feed(flow, "I (5100) KOTA: cmd wifi_clear ok=1 restart=1")
feed(flow, BOOT.format(mode="matter", last="usb_wifi_clear"))
assert flow.step == Step.DONE and "Matter" in events[-1].text
def test_read_current_settings():
flow, sent, events, _ = make("read")
flow.start()
feed(flow, PING)
assert sent[-1] == "kota wifi get"
feed(flow, "I (5100) KOTA: cmd wifi_get ok=1 ssid=426975726f password_set=1 mode=wifi")
assert flow.step == Step.DONE and flow.info.ssid == "Biuro" and flow.info.password_set
assert "local Wi-Fi" in events[-1].text
def test_not_connected():
events = []
flow = WifiFlow("read", lambda c: False, events.append)
flow.start()
assert flow.step == Step.FAILED and "not connected" in events[-1].text
# ---------------------------------------------------------------- engine
def test_engine_treats_usb_wifi_restart_as_intentional_and_reads_replies():
e = DiagnosticsEngine()
for t in ["ESP-ROM:esp32s3-20210327", "I (1790) KOTA: i2c SDA=1 SCL=1 0x39=AS7341",
BOOT.format(mode="matter", last="none"), PING,
"I (5100) KOTA: cmd wifi_set ok=1 restart=1", "W (5101) KOTA: restart reason=usb_wifi_set",
"ESP-ROM:esp32s3-20210327", "rst:0x3 (RTC_SW_SYS_RST),boot:0xb (SPI_FAST_FLASH_BOOT)",
BOOT.format(mode="wifi", last="usb_wifi_set"),
"I (6000) KOTA: cmd wifi_get ok=1 ssid=426975726f password_set=1 mode=wifi",
HEALTH.format(wifi="connected", rssi=-60)]:
e.feed(parse_line(t))
r = e.report()
assert not any(f.rule_id.startswith("reboot.") for rc in r.roots for f in [rc.finding, *rc.consequences])
assert e.console_api == 1
box = dict((t, x) for t, x, _ in r.box)
assert "network 'Biuro'" in box["Wi-Fi config"] and "Wi-Fi connected (-60 dBm)" in box["Health"]
assert any(m == "wifi_connected" and t is not None for m, _, t in r.milestones)
def test_live_v13_box_answers_usb_commands():
# Real capture (2026-09-29): box 14:C1:9F:57:72:48 after flashing merged-binary-v13.bin App-only;
# the Wi-Fi tab's read flow sent "kota ping" and "kota wifi get".
from pathlib import Path
from kota_tech.core.logfile import read_log_file
e = DiagnosticsEngine()
for ln in read_log_file(Path(__file__).parent / "fixtures" / "live_boot_14C19F577248_v13_usb_console.txt"):
e.feed(ln)
r = e.report()
assert e.firmware.elf_sha.startswith("3ae273ec") and e.console_api == 1
assert dict((t, x) for t, x, _ in r.box)["Wi-Fi config"] == "no network on the SD card, mode matter"
assert not any(f.rule_id.startswith("other.") for f in e.findings.values()) # logs intact via the driver
+19
View File
@@ -0,0 +1,19 @@
"""The whole window builds (catches errors that only show when the app starts)."""
import os
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
def test_main_window_builds_with_all_tabs():
from PySide6.QtWidgets import QApplication
from kota_tech.ui.main_window import MainWindow
app = QApplication.instance() or QApplication([])
w = MainWindow()
tabs = w.centralWidget()
assert [tabs.tabText(i) for i in range(tabs.count())] == \
["Quick start", "Serial monitor", "Flash firmware", "Wi-Fi (USB)", "SD card"]
assert not w.wifi_tab.write_btn.isEnabled() # nothing connected, nothing typed
w.serial_tab.shutdown()
app.processEvents()
+74
View File
@@ -0,0 +1,74 @@
#!/bin/bash
# KOTA Sensorbox Technician Tool - update to the newest released version.
# Checks Gitea for the newest release tag (vX.Y) and downloads only what changed (git).
# Works in a git clone and in a folder unpacked from a release zip (it is connected on first run).
# If Finder refuses to open this file, run it once as: bash update_macos.command
cd "$(dirname "$0")" || exit 1
REPO_URL="${KOTA_REPO_URL:-https://gitea.kota-app.com/kkallas/kota-technician-tool.git}"
export UV_PROJECT_ENVIRONMENT="${UV_PROJECT_ENVIRONMENT:-$HOME/Library/Caches/KotaTechnicianTool/venv}"
export PATH="$HOME/.local/bin:$PATH"
finish() {
[ -z "$KOTA_NO_PAUSE" ] && [ -t 0 ] && read -r -p "Press Enter to close..." _
exit "$1"
}
fail() { echo; echo "[!] $*"; echo "[!] Update did not finish."; finish 1; }
# ---- git (macOS: the Command Line Tools installer offers it) --------------
if ! git --version >/dev/null 2>&1; then
if [ "$(uname)" = Darwin ]; then
xcode-select --install >/dev/null 2>&1
fail "Git is being installed (Apple Command Line Tools). Run this again when the installer has finished."
fi
fail "Git is not installed."
fi
# ---- connect a folder unpacked from a zip ----------------------------------
if [ ! -d .git ]; then
echo "Connecting this folder to $REPO_URL ..."
git init -q && git remote add origin "$REPO_URL" || fail "Cannot set up git in this folder."
fi
# A developer copy follows a branch; it is updated with "git pull", not here.
if git rev-parse -q --verify HEAD >/dev/null 2>&1 && branch=$(git symbolic-ref -q --short HEAD); then
echo "This is a developer copy on branch $branch. Update it with: git pull"
finish 0
fi
echo "Checking for a new version..."
git fetch --quiet --force --tags origin ||
fail "Cannot reach $REPO_URL. Check the Internet connection and your Gitea login, then try again."
latest=$(git tag -l 'v*' --sort=-v:refname | head -n 1)
[ -n "$latest" ] || fail "No released version found on the server."
current=$(git describe --tags --exact-match HEAD 2>/dev/null)
if [ "$current" = "$latest" ]; then
echo "You already have the newest version $latest."
else
if [ -n "$current" ]; then
if [ -n "$(git status --porcelain --untracked-files=no)" ]; then
echo "Some tool files in this folder were changed by hand. They will be replaced by $latest."
read -r -p "Continue? [y/N] " answer
[[ "$answer" =~ ^[Yy]$ ]] || fail "Cancelled."
fi
echo "Updating $current -> $latest. Changes:"
git --no-pager log --oneline --no-decorate "$current..$latest"
else
echo "Installing $latest..."
fi
git -c advice.detachedHead=false checkout -q -f "$latest" || fail "Checkout of $latest failed."
echo "Now on $latest."
fi
# ---- Python libraries (only what changed) ----------------------------------
if ! command -v uv >/dev/null 2>&1; then
echo "Installing uv (Python package runner, current user only)..."
curl -LsSf https://astral.sh/uv/install.sh | sh || fail "uv installation failed. Ask the firmware team for help."
fi
echo "Checking Python libraries..."
uv sync --frozen --no-dev --python 3.12 --quiet || fail "Installing Python libraries failed."
echo
echo "Done. Start the tool with run_macos.command."
finish 0
+107
View File
@@ -0,0 +1,107 @@
@echo off
rem KOTA Sensorbox Technician Tool - update to the newest released version.
rem Checks Gitea for the newest release tag (vX.Y) and downloads only what changed (git).
rem Works in a git clone and in a folder unpacked from a release zip (it is connected on first run).
setlocal EnableDelayedExpansion
cd /d "%~dp0"
title KOTA Technician Tool - update
if not defined KOTA_REPO_URL set "KOTA_REPO_URL=https://gitea.kota-app.com/kkallas/kota-technician-tool.git"
set "UV_PROJECT_ENVIRONMENT=%LOCALAPPDATA%\KotaTechnicianTool\venv"
set "PATH=%USERPROFILE%\.local\bin;%ProgramFiles%\Git\cmd;%PATH%"
rem ---- git ----------------------------------------------------------------
where git >nul 2>nul
if errorlevel 1 (
echo Git is not installed. It is needed to download updates.
choice /m "Install Git for Windows now"
if errorlevel 2 goto :fail
winget install --id Git.Git -e --source winget --accept-package-agreements
where git >nul 2>nul
if errorlevel 1 (
echo ERROR: Git installation failed. Install it from https://git-scm.com and run this again.
goto :fail
)
)
rem ---- connect a folder unpacked from a zip ---------------------------------
if not exist ".git" (
echo Connecting this folder to %KOTA_REPO_URL% ...
git init -q || goto :fail
git remote add origin "%KOTA_REPO_URL%" || goto :fail
)
rem A developer copy follows a branch; it is updated with "git pull", not here.
git rev-parse -q --verify HEAD >nul 2>nul
if not errorlevel 1 (
for /f "delims=" %%b in ('git symbolic-ref -q --short HEAD 2^>nul') do (
echo This is a developer copy on branch %%b. Update it with: git pull
goto :done
)
)
echo Checking for a new version...
git fetch --quiet --force --tags origin
if errorlevel 1 (
echo ERROR: Cannot reach %KOTA_REPO_URL%.
echo Check the Internet connection and your Gitea login, then try again.
goto :fail
)
set "LATEST="
for /f "delims=" %%t in ('git tag -l "v*" --sort^=-v:refname') do if not defined LATEST set "LATEST=%%t"
if not defined LATEST (
echo ERROR: No released version found on the server.
goto :fail
)
set "CURRENT="
for /f "delims=" %%t in ('git describe --tags --exact-match HEAD 2^>nul') do set "CURRENT=%%t"
if "%CURRENT%"=="%LATEST%" (
echo You already have the newest version %LATEST%.
goto :deps
)
if defined CURRENT (
for /f "delims=" %%s in ('git status --porcelain --untracked-files^=no') do set "DIRTY=1"
if defined DIRTY (
echo Some tool files in this folder were changed by hand. They will be replaced by %LATEST%.
choice /m "Continue"
if errorlevel 2 goto :fail
)
echo Updating %CURRENT% -^> %LATEST%. Changes:
git --no-pager log --oneline --no-decorate "%CURRENT%..%LATEST%"
) else (
echo Installing %LATEST%...
)
git -c advice.detachedHead=false checkout -q -f "%LATEST%"
if errorlevel 1 goto :fail
echo Now on %LATEST%.
rem ---- Python libraries (only what changed) ----------------------------------
:deps
where uv >nul 2>nul
if errorlevel 1 (
echo Installing uv ^(Python package runner, current user only^)...
powershell -NoProfile -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
)
where uv >nul 2>nul
if errorlevel 1 (
echo ERROR: uv installation failed. Ask the firmware team for help.
goto :fail
)
echo Checking Python libraries...
uv sync --frozen --no-dev --python 3.12 --quiet
if errorlevel 1 goto :fail
echo.
echo Done. Start the tool with run_windows.bat.
:done
if not defined KOTA_NO_PAUSE pause
exit /b 0
:fail
echo.
echo ERROR: Update did not finish.
if not defined KOTA_NO_PAUSE pause
exit /b 1
Generated
+1 -1
View File
@@ -250,7 +250,7 @@ wheels = [
[[package]] [[package]]
name = "kota-technician-tool" name = "kota-technician-tool"
version = "0.8.0" version = "0.9.0"
source = { virtual = "." } source = { virtual = "." }
dependencies = [ dependencies = [
{ name = "esptool" }, { name = "esptool" },