diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/proj-ib-lighting-rs485-zarki.yaml b/proj-ib-lighting-rs485-zarki.yaml index 3a47859..214118d 100644 --- a/proj-ib-lighting-rs485-zarki.yaml +++ b/proj-ib-lighting-rs485-zarki.yaml @@ -278,7 +278,7 @@ - io_id: "input.t.1" status: "ok" mapping: "" - description: """ + description: "" - io_id: "input.t.2" status: "ok" mapping: "" diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/proj-ib-lighting-rs485-zarki.yaml b/proj-ib-lighting-rs485-zarki.yaml index 3a47859..214118d 100644 --- a/proj-ib-lighting-rs485-zarki.yaml +++ b/proj-ib-lighting-rs485-zarki.yaml @@ -278,7 +278,7 @@ - io_id: "input.t.1" status: "ok" mapping: "" - description: """ + description: "" - io_id: "input.t.2" status: "ok" mapping: "" diff --git a/testowe/check_perm.sh b/testowe/check_perm.sh new file mode 100755 index 0000000..a9f141e --- /dev/null +++ b/testowe/check_perm.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +chown -R root:root /ibsystem +chmod 755 /ibsystem/*.sh +chmod 755 /ibsystem/ibvunit/ibvunit +chmod 755 /ibsystem/ibmanager/ibmanager +chmod 755 /ibsystem/ibls diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/proj-ib-lighting-rs485-zarki.yaml b/proj-ib-lighting-rs485-zarki.yaml index 3a47859..214118d 100644 --- a/proj-ib-lighting-rs485-zarki.yaml +++ b/proj-ib-lighting-rs485-zarki.yaml @@ -278,7 +278,7 @@ - io_id: "input.t.1" status: "ok" mapping: "" - description: """ + description: "" - io_id: "input.t.2" status: "ok" mapping: "" diff --git a/testowe/check_perm.sh b/testowe/check_perm.sh new file mode 100755 index 0000000..a9f141e --- /dev/null +++ b/testowe/check_perm.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +chown -R root:root /ibsystem +chmod 755 /ibsystem/*.sh +chmod 755 /ibsystem/ibvunit/ibvunit +chmod 755 /ibsystem/ibmanager/ibmanager +chmod 755 /ibsystem/ibls diff --git a/testowe/check_status.py b/testowe/check_status.py new file mode 100644 index 0000000..6457cef --- /dev/null +++ b/testowe/check_status.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., do.x + output_name = line.split('=')[0].strip() + output_name = output_name.split('.')[-2] + '.' + output_name.split('.')[-1] # do.x + print(f"Active output: {output_name}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/proj-ib-lighting-rs485-zarki.yaml b/proj-ib-lighting-rs485-zarki.yaml index 3a47859..214118d 100644 --- a/proj-ib-lighting-rs485-zarki.yaml +++ b/proj-ib-lighting-rs485-zarki.yaml @@ -278,7 +278,7 @@ - io_id: "input.t.1" status: "ok" mapping: "" - description: """ + description: "" - io_id: "input.t.2" status: "ok" mapping: "" diff --git a/testowe/check_perm.sh b/testowe/check_perm.sh new file mode 100755 index 0000000..a9f141e --- /dev/null +++ b/testowe/check_perm.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +chown -R root:root /ibsystem +chmod 755 /ibsystem/*.sh +chmod 755 /ibsystem/ibvunit/ibvunit +chmod 755 /ibsystem/ibmanager/ibmanager +chmod 755 /ibsystem/ibls diff --git a/testowe/check_status.py b/testowe/check_status.py new file mode 100644 index 0000000..6457cef --- /dev/null +++ b/testowe/check_status.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., do.x + output_name = line.split('=')[0].strip() + output_name = output_name.split('.')[-2] + '.' + output_name.split('.')[-1] # do.x + print(f"Active output: {output_name}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status.sh b/testowe/check_status.sh new file mode 100755 index 0000000..f0aa2ba --- /dev/null +++ b/testowe/check_status.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# Funkcja wyświetlająca pomoc +show_help() { + echo "Użycie: $0 [OPCJE]" + echo + echo "Opcje:" + echo " --show_active_output Wyświetl tylko sterowniki z aktywnymi wyjściami" + echo " --all Wyświetl pełne informacje o sterownikach" + echo " --help Wyświetl tę pomoc" + exit 1 +} + +# Jeśli nie podano żadnych argumentów, wyświetl pomoc +if [ $# -eq 0 ]; then + show_help +fi + +# Domyślne wartości parametrów +show_active_output=false # Domyślnie nie pokazujemy aktywnych wyjść +show_all=false # Domyślnie nie pokazujemy wszystkich informacji + +# Sprawdzenie, jakie parametry zostały podane +for arg in "$@"; do + case $arg in + --show_active_output) + show_active_output=true + shift + ;; + --all) + show_all=true + shift + ;; + --help) + show_help + shift + ;; + *) + echo "Nieznana opcja: $arg" + show_help + ;; + esac +done + +# Plik XML, z którego będziemy pobierać wartości Address +xml_file="ibvunit/ibvunit.xml" + +# Wyciągnięcie wartości Address tylko z sekcji +awk '//' "$xml_file" | grep -oP 'Address="\K\d+' | while read -r address; do + # Uruchomienie polecenia dla każdej wartości Address + output=$(./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.$address.out;);") + + # Jeśli parametr show_all jest ustawiony na 'true', pokaż pełne wyjście polecenia + if [ "$show_all" = true ]; then + echo "Sterownik id.$address:" + echo "$output" + fi + + # Jeśli parametr show_active_output jest ustawiony na 'true', wyświetl tylko sterowniki z włączonymi wyjściami + if [ "$show_active_output" = true ]; then + active_outputs=$(echo "$output" | grep -oP 'do\.\d+ = 1') + + if [ -n "$active_outputs" ]; then + echo "Sterownik id.$address ma aktywne wyjścia:" + echo "$active_outputs" | while read -r line; do + output_name=$(echo "$line" | cut -d' ' -f1) # wyciągnięcie nazwy wyjścia, np. do.0 + echo "Włączone wyjście: $output_name" + done + fi + fi +done + diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/proj-ib-lighting-rs485-zarki.yaml b/proj-ib-lighting-rs485-zarki.yaml index 3a47859..214118d 100644 --- a/proj-ib-lighting-rs485-zarki.yaml +++ b/proj-ib-lighting-rs485-zarki.yaml @@ -278,7 +278,7 @@ - io_id: "input.t.1" status: "ok" mapping: "" - description: """ + description: "" - io_id: "input.t.2" status: "ok" mapping: "" diff --git a/testowe/check_perm.sh b/testowe/check_perm.sh new file mode 100755 index 0000000..a9f141e --- /dev/null +++ b/testowe/check_perm.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +chown -R root:root /ibsystem +chmod 755 /ibsystem/*.sh +chmod 755 /ibsystem/ibvunit/ibvunit +chmod 755 /ibsystem/ibmanager/ibmanager +chmod 755 /ibsystem/ibls diff --git a/testowe/check_status.py b/testowe/check_status.py new file mode 100644 index 0000000..6457cef --- /dev/null +++ b/testowe/check_status.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., do.x + output_name = line.split('=')[0].strip() + output_name = output_name.split('.')[-2] + '.' + output_name.split('.')[-1] # do.x + print(f"Active output: {output_name}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status.sh b/testowe/check_status.sh new file mode 100755 index 0000000..f0aa2ba --- /dev/null +++ b/testowe/check_status.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# Funkcja wyświetlająca pomoc +show_help() { + echo "Użycie: $0 [OPCJE]" + echo + echo "Opcje:" + echo " --show_active_output Wyświetl tylko sterowniki z aktywnymi wyjściami" + echo " --all Wyświetl pełne informacje o sterownikach" + echo " --help Wyświetl tę pomoc" + exit 1 +} + +# Jeśli nie podano żadnych argumentów, wyświetl pomoc +if [ $# -eq 0 ]; then + show_help +fi + +# Domyślne wartości parametrów +show_active_output=false # Domyślnie nie pokazujemy aktywnych wyjść +show_all=false # Domyślnie nie pokazujemy wszystkich informacji + +# Sprawdzenie, jakie parametry zostały podane +for arg in "$@"; do + case $arg in + --show_active_output) + show_active_output=true + shift + ;; + --all) + show_all=true + shift + ;; + --help) + show_help + shift + ;; + *) + echo "Nieznana opcja: $arg" + show_help + ;; + esac +done + +# Plik XML, z którego będziemy pobierać wartości Address +xml_file="ibvunit/ibvunit.xml" + +# Wyciągnięcie wartości Address tylko z sekcji +awk '//' "$xml_file" | grep -oP 'Address="\K\d+' | while read -r address; do + # Uruchomienie polecenia dla każdej wartości Address + output=$(./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.$address.out;);") + + # Jeśli parametr show_all jest ustawiony na 'true', pokaż pełne wyjście polecenia + if [ "$show_all" = true ]; then + echo "Sterownik id.$address:" + echo "$output" + fi + + # Jeśli parametr show_active_output jest ustawiony na 'true', wyświetl tylko sterowniki z włączonymi wyjściami + if [ "$show_active_output" = true ]; then + active_outputs=$(echo "$output" | grep -oP 'do\.\d+ = 1') + + if [ -n "$active_outputs" ]; then + echo "Sterownik id.$address ma aktywne wyjścia:" + echo "$active_outputs" | while read -r line; do + output_name=$(echo "$line" | cut -d' ' -f1) # wyciągnięcie nazwy wyjścia, np. do.0 + echo "Włączone wyjście: $output_name" + done + fi + fi +done + diff --git a/testowe/check_status1.py b/testowe/check_status1.py new file mode 100644 index 0000000..7ca8f94 --- /dev/null +++ b/testowe/check_status1.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Read dok.txt and create a mapping of output names to their descriptions +def load_output_descriptions(dok_file): + descriptions = {} + current_id = None + with open(dok_file, 'r') as file: + for line in file: + line = line.strip() + if line.startswith("id."): # New controller section + current_id = line.split(".")[1] + elif current_id is not None and line.startswith("output.do."): + output_name = f"rs.0.id.{current_id}.{line.split('=')[0].strip()}" + description = line.split('=')[1].strip() + descriptions[output_name] = description + return descriptions + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # Load output descriptions from dok.txt + output_descriptions = load_output_descriptions(dok_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., rs.0.id.39.output.do.2 + output_name = line.split('=')[0].strip() + output_identifier = output_name.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier.split('.')[-1]}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier.split('.')[-1]}" # Corrected to just 'output.do.x' + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + print(f"Controller id.{address} output.{output_identifier.split('.')[-1]} name: {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/proj-ib-lighting-rs485-zarki.yaml b/proj-ib-lighting-rs485-zarki.yaml index 3a47859..214118d 100644 --- a/proj-ib-lighting-rs485-zarki.yaml +++ b/proj-ib-lighting-rs485-zarki.yaml @@ -278,7 +278,7 @@ - io_id: "input.t.1" status: "ok" mapping: "" - description: """ + description: "" - io_id: "input.t.2" status: "ok" mapping: "" diff --git a/testowe/check_perm.sh b/testowe/check_perm.sh new file mode 100755 index 0000000..a9f141e --- /dev/null +++ b/testowe/check_perm.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +chown -R root:root /ibsystem +chmod 755 /ibsystem/*.sh +chmod 755 /ibsystem/ibvunit/ibvunit +chmod 755 /ibsystem/ibmanager/ibmanager +chmod 755 /ibsystem/ibls diff --git a/testowe/check_status.py b/testowe/check_status.py new file mode 100644 index 0000000..6457cef --- /dev/null +++ b/testowe/check_status.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., do.x + output_name = line.split('=')[0].strip() + output_name = output_name.split('.')[-2] + '.' + output_name.split('.')[-1] # do.x + print(f"Active output: {output_name}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status.sh b/testowe/check_status.sh new file mode 100755 index 0000000..f0aa2ba --- /dev/null +++ b/testowe/check_status.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# Funkcja wyświetlająca pomoc +show_help() { + echo "Użycie: $0 [OPCJE]" + echo + echo "Opcje:" + echo " --show_active_output Wyświetl tylko sterowniki z aktywnymi wyjściami" + echo " --all Wyświetl pełne informacje o sterownikach" + echo " --help Wyświetl tę pomoc" + exit 1 +} + +# Jeśli nie podano żadnych argumentów, wyświetl pomoc +if [ $# -eq 0 ]; then + show_help +fi + +# Domyślne wartości parametrów +show_active_output=false # Domyślnie nie pokazujemy aktywnych wyjść +show_all=false # Domyślnie nie pokazujemy wszystkich informacji + +# Sprawdzenie, jakie parametry zostały podane +for arg in "$@"; do + case $arg in + --show_active_output) + show_active_output=true + shift + ;; + --all) + show_all=true + shift + ;; + --help) + show_help + shift + ;; + *) + echo "Nieznana opcja: $arg" + show_help + ;; + esac +done + +# Plik XML, z którego będziemy pobierać wartości Address +xml_file="ibvunit/ibvunit.xml" + +# Wyciągnięcie wartości Address tylko z sekcji +awk '//' "$xml_file" | grep -oP 'Address="\K\d+' | while read -r address; do + # Uruchomienie polecenia dla każdej wartości Address + output=$(./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.$address.out;);") + + # Jeśli parametr show_all jest ustawiony na 'true', pokaż pełne wyjście polecenia + if [ "$show_all" = true ]; then + echo "Sterownik id.$address:" + echo "$output" + fi + + # Jeśli parametr show_active_output jest ustawiony na 'true', wyświetl tylko sterowniki z włączonymi wyjściami + if [ "$show_active_output" = true ]; then + active_outputs=$(echo "$output" | grep -oP 'do\.\d+ = 1') + + if [ -n "$active_outputs" ]; then + echo "Sterownik id.$address ma aktywne wyjścia:" + echo "$active_outputs" | while read -r line; do + output_name=$(echo "$line" | cut -d' ' -f1) # wyciągnięcie nazwy wyjścia, np. do.0 + echo "Włączone wyjście: $output_name" + done + fi + fi +done + diff --git a/testowe/check_status1.py b/testowe/check_status1.py new file mode 100644 index 0000000..7ca8f94 --- /dev/null +++ b/testowe/check_status1.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Read dok.txt and create a mapping of output names to their descriptions +def load_output_descriptions(dok_file): + descriptions = {} + current_id = None + with open(dok_file, 'r') as file: + for line in file: + line = line.strip() + if line.startswith("id."): # New controller section + current_id = line.split(".")[1] + elif current_id is not None and line.startswith("output.do."): + output_name = f"rs.0.id.{current_id}.{line.split('=')[0].strip()}" + description = line.split('=')[1].strip() + descriptions[output_name] = description + return descriptions + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # Load output descriptions from dok.txt + output_descriptions = load_output_descriptions(dok_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., rs.0.id.39.output.do.2 + output_name = line.split('=')[0].strip() + output_identifier = output_name.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier.split('.')[-1]}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier.split('.')[-1]}" # Corrected to just 'output.do.x' + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + print(f"Controller id.{address} output.{output_identifier.split('.')[-1]} name: {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status2.py b/testowe/check_status2.py new file mode 100644 index 0000000..5556d58 --- /dev/null +++ b/testowe/check_status2.py @@ -0,0 +1,81 @@ +import argparse + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +def parse_arguments(): + parser = argparse.ArgumentParser(description="Controller output monitoring script.") + parser.add_argument('--all', action='store_true', help='Show all controller outputs.') + parser.add_argument('--show-active-output', action='store_true', help='Show only active outputs.') + parser.add_argument('--show-id', type=int, help='Show outputs for a specific controller ID.') + return parser.parse_args() + +def read_dok_file(dok_file): + output_descriptions = {} + controllers = {} + + with open(dok_file, 'r') as f: + lines = f.readlines() + current_id = None + for line in lines: + line = line.strip() + if line.startswith("id."): + current_id = line.split('.')[1] + controllers[current_id] = {'active_outputs': [], 'name': f'Controller {current_id}'} + elif current_id and "=" in line: + key, value = line.split("=") + output_key = key.strip() + output_descriptions[output_key] = value.strip() + # Check if the output key is an active output for the current controller + if output_key.startswith('output.do.'): + controllers[current_id]['active_outputs'].append(output_key) + + return output_descriptions, controllers + +def main(): + args = parse_arguments() + + # Read output descriptions from dok.txt and create controllers dictionary + output_descriptions, controllers = read_dok_file(dok_file) + + if not (args.all or args.show_active_output): + print("Error: You must provide either --all or --show-active-output.") + return + + for address, controller in controllers.items(): + if args.show_id is not None and int(address) != args.show_id: + continue + + if args.all: + print(f"{controller['name']}:") + for output in controller['active_outputs']: + description = output_descriptions.get(output, "Unknown output") + print(f"{output} name: {description}") + + if args.show_active_output: + active_outputs = controller['active_outputs'] + if active_outputs: + for line in active_outputs: + output_identifier = line.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier}" + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + # Change output to include the full output key + print(f"Controller id.{address} output.do.{output_identifier} - {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/proj-ib-lighting-rs485-zarki.yaml b/proj-ib-lighting-rs485-zarki.yaml index 3a47859..214118d 100644 --- a/proj-ib-lighting-rs485-zarki.yaml +++ b/proj-ib-lighting-rs485-zarki.yaml @@ -278,7 +278,7 @@ - io_id: "input.t.1" status: "ok" mapping: "" - description: """ + description: "" - io_id: "input.t.2" status: "ok" mapping: "" diff --git a/testowe/check_perm.sh b/testowe/check_perm.sh new file mode 100755 index 0000000..a9f141e --- /dev/null +++ b/testowe/check_perm.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +chown -R root:root /ibsystem +chmod 755 /ibsystem/*.sh +chmod 755 /ibsystem/ibvunit/ibvunit +chmod 755 /ibsystem/ibmanager/ibmanager +chmod 755 /ibsystem/ibls diff --git a/testowe/check_status.py b/testowe/check_status.py new file mode 100644 index 0000000..6457cef --- /dev/null +++ b/testowe/check_status.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., do.x + output_name = line.split('=')[0].strip() + output_name = output_name.split('.')[-2] + '.' + output_name.split('.')[-1] # do.x + print(f"Active output: {output_name}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status.sh b/testowe/check_status.sh new file mode 100755 index 0000000..f0aa2ba --- /dev/null +++ b/testowe/check_status.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# Funkcja wyświetlająca pomoc +show_help() { + echo "Użycie: $0 [OPCJE]" + echo + echo "Opcje:" + echo " --show_active_output Wyświetl tylko sterowniki z aktywnymi wyjściami" + echo " --all Wyświetl pełne informacje o sterownikach" + echo " --help Wyświetl tę pomoc" + exit 1 +} + +# Jeśli nie podano żadnych argumentów, wyświetl pomoc +if [ $# -eq 0 ]; then + show_help +fi + +# Domyślne wartości parametrów +show_active_output=false # Domyślnie nie pokazujemy aktywnych wyjść +show_all=false # Domyślnie nie pokazujemy wszystkich informacji + +# Sprawdzenie, jakie parametry zostały podane +for arg in "$@"; do + case $arg in + --show_active_output) + show_active_output=true + shift + ;; + --all) + show_all=true + shift + ;; + --help) + show_help + shift + ;; + *) + echo "Nieznana opcja: $arg" + show_help + ;; + esac +done + +# Plik XML, z którego będziemy pobierać wartości Address +xml_file="ibvunit/ibvunit.xml" + +# Wyciągnięcie wartości Address tylko z sekcji +awk '//' "$xml_file" | grep -oP 'Address="\K\d+' | while read -r address; do + # Uruchomienie polecenia dla każdej wartości Address + output=$(./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.$address.out;);") + + # Jeśli parametr show_all jest ustawiony na 'true', pokaż pełne wyjście polecenia + if [ "$show_all" = true ]; then + echo "Sterownik id.$address:" + echo "$output" + fi + + # Jeśli parametr show_active_output jest ustawiony na 'true', wyświetl tylko sterowniki z włączonymi wyjściami + if [ "$show_active_output" = true ]; then + active_outputs=$(echo "$output" | grep -oP 'do\.\d+ = 1') + + if [ -n "$active_outputs" ]; then + echo "Sterownik id.$address ma aktywne wyjścia:" + echo "$active_outputs" | while read -r line; do + output_name=$(echo "$line" | cut -d' ' -f1) # wyciągnięcie nazwy wyjścia, np. do.0 + echo "Włączone wyjście: $output_name" + done + fi + fi +done + diff --git a/testowe/check_status1.py b/testowe/check_status1.py new file mode 100644 index 0000000..7ca8f94 --- /dev/null +++ b/testowe/check_status1.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Read dok.txt and create a mapping of output names to their descriptions +def load_output_descriptions(dok_file): + descriptions = {} + current_id = None + with open(dok_file, 'r') as file: + for line in file: + line = line.strip() + if line.startswith("id."): # New controller section + current_id = line.split(".")[1] + elif current_id is not None and line.startswith("output.do."): + output_name = f"rs.0.id.{current_id}.{line.split('=')[0].strip()}" + description = line.split('=')[1].strip() + descriptions[output_name] = description + return descriptions + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # Load output descriptions from dok.txt + output_descriptions = load_output_descriptions(dok_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., rs.0.id.39.output.do.2 + output_name = line.split('=')[0].strip() + output_identifier = output_name.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier.split('.')[-1]}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier.split('.')[-1]}" # Corrected to just 'output.do.x' + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + print(f"Controller id.{address} output.{output_identifier.split('.')[-1]} name: {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status2.py b/testowe/check_status2.py new file mode 100644 index 0000000..5556d58 --- /dev/null +++ b/testowe/check_status2.py @@ -0,0 +1,81 @@ +import argparse + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +def parse_arguments(): + parser = argparse.ArgumentParser(description="Controller output monitoring script.") + parser.add_argument('--all', action='store_true', help='Show all controller outputs.') + parser.add_argument('--show-active-output', action='store_true', help='Show only active outputs.') + parser.add_argument('--show-id', type=int, help='Show outputs for a specific controller ID.') + return parser.parse_args() + +def read_dok_file(dok_file): + output_descriptions = {} + controllers = {} + + with open(dok_file, 'r') as f: + lines = f.readlines() + current_id = None + for line in lines: + line = line.strip() + if line.startswith("id."): + current_id = line.split('.')[1] + controllers[current_id] = {'active_outputs': [], 'name': f'Controller {current_id}'} + elif current_id and "=" in line: + key, value = line.split("=") + output_key = key.strip() + output_descriptions[output_key] = value.strip() + # Check if the output key is an active output for the current controller + if output_key.startswith('output.do.'): + controllers[current_id]['active_outputs'].append(output_key) + + return output_descriptions, controllers + +def main(): + args = parse_arguments() + + # Read output descriptions from dok.txt and create controllers dictionary + output_descriptions, controllers = read_dok_file(dok_file) + + if not (args.all or args.show_active_output): + print("Error: You must provide either --all or --show-active-output.") + return + + for address, controller in controllers.items(): + if args.show_id is not None and int(address) != args.show_id: + continue + + if args.all: + print(f"{controller['name']}:") + for output in controller['active_outputs']: + description = output_descriptions.get(output, "Unknown output") + print(f"{output} name: {description}") + + if args.show_active_output: + active_outputs = controller['active_outputs'] + if active_outputs: + for line in active_outputs: + output_identifier = line.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier}" + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + # Change output to include the full output key + print(f"Controller id.{address} output.do.{output_identifier} - {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/desc_gen.py b/testowe/desc_gen.py new file mode 100644 index 0000000..95e1757 --- /dev/null +++ b/testowe/desc_gen.py @@ -0,0 +1,118 @@ +import re + +def load_device_list(file_path): + """Wczytuje listę urządzeń z pliku.""" + with open(file_path, 'r', encoding='utf-8') as file: + lines = [line.strip() for line in file if line.strip()] + return lines + +def parse_devices(lines): + """Grupuje urządzenia według ID, pomijając te, które już mają opis.""" + devices = {} + for line in lines: + if '-' in line: # Pomija urządzenia, które już mają opis + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id not in devices: + devices[device_id] = [] + devices[device_id].append(line) + return devices + +def load_existing_descriptions(file_path): + """Wczytuje istniejące opisy z pliku wynikowego.""" + try: + with open(file_path, 'r', encoding='utf-8') as file: + return {line.split(" - ")[0].strip(): line.strip() for line in file if " - " in line} + except FileNotFoundError: + return {} + +def generate_descriptions(devices, existing_descriptions): + """Interaktywnie generuje opisy dla urządzeń.""" + descriptions = {} + try: + for device_id, components in devices.items(): + print(f"\nID urządzenia: {device_id}") + # Generowanie opisu głównego urządzenia + if f"id {device_id}" in existing_descriptions: + current_desc = existing_descriptions[f"id {device_id}"] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input("Czy chcesz zmodyfikować ten opis? (tak/nie): ").strip().lower() + if modify == "nie": + continue + else: + description = input(f"Podaj nowy opis dla ID {device_id} (np. wiatrołap/kuchnia): ").strip() + if not description: + description = "brak" + descriptions[device_id] = {f"id {device_id}": description} + + # Generowanie opisów dla komponentów urządzenia + for component in components: + if component in existing_descriptions: + current_desc = existing_descriptions[component] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input(f"Czy chcesz zmodyfikować opis dla {component}? (tak/nie): ").strip().lower() + if modify == "nie": + continue + component_desc = input(f"Podaj opis dla {component}: ").strip() + if not component_desc: + component_desc = "brak" + descriptions.setdefault(device_id, {})[component] = component_desc + + except (KeyboardInterrupt, EOFError): # Obsługuje Ctrl+C i Ctrl+Z + print("\nZatrzymano interakcję. Zapisywanie danych...") + return descriptions, True + + return descriptions, False + +def save_descriptions(file_path, descriptions, original_lines, existing_descriptions): + """Zapisuje opisy do pliku, zachowując istniejącą strukturę.""" + with open(file_path, 'w', encoding='utf-8') as file: + for line in original_lines: + if '-' in line: + file.write(line + '\n') + continue + if line in existing_descriptions: + file.write(existing_descriptions[line] + '\n') + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id in descriptions and line in descriptions[device_id]: + file.write(f"{line} - {descriptions[device_id][line]}\n") + else: + file.write(line + '\n') + else: + file.write(line + '\n') + +def main(): + input_file = 'dok.txt' + output_file = 'dok_output.txt' + + print("Wczytywanie urządzeń i istniejących opisów...") + original_lines = load_device_list(input_file) + devices = parse_devices(original_lines) + existing_descriptions = load_existing_descriptions(output_file) + + if not devices: + print("Brak urządzeń do opisania.") + return + + print(f"Znaleziono {len(devices)} urządzeń do opisania.") + + all_descriptions = {} + while devices: + descriptions, should_exit = generate_descriptions(devices, existing_descriptions) + all_descriptions.update(descriptions) + if should_exit: + break + + print("\nZapisywanie opisów do pliku...") + save_descriptions(output_file, all_descriptions, original_lines, existing_descriptions) + print(f"Opisy zapisano w pliku {output_file}.") + print("Zakończono.") + +if __name__ == "__main__": + main() + diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/proj-ib-lighting-rs485-zarki.yaml b/proj-ib-lighting-rs485-zarki.yaml index 3a47859..214118d 100644 --- a/proj-ib-lighting-rs485-zarki.yaml +++ b/proj-ib-lighting-rs485-zarki.yaml @@ -278,7 +278,7 @@ - io_id: "input.t.1" status: "ok" mapping: "" - description: """ + description: "" - io_id: "input.t.2" status: "ok" mapping: "" diff --git a/testowe/check_perm.sh b/testowe/check_perm.sh new file mode 100755 index 0000000..a9f141e --- /dev/null +++ b/testowe/check_perm.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +chown -R root:root /ibsystem +chmod 755 /ibsystem/*.sh +chmod 755 /ibsystem/ibvunit/ibvunit +chmod 755 /ibsystem/ibmanager/ibmanager +chmod 755 /ibsystem/ibls diff --git a/testowe/check_status.py b/testowe/check_status.py new file mode 100644 index 0000000..6457cef --- /dev/null +++ b/testowe/check_status.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., do.x + output_name = line.split('=')[0].strip() + output_name = output_name.split('.')[-2] + '.' + output_name.split('.')[-1] # do.x + print(f"Active output: {output_name}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status.sh b/testowe/check_status.sh new file mode 100755 index 0000000..f0aa2ba --- /dev/null +++ b/testowe/check_status.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# Funkcja wyświetlająca pomoc +show_help() { + echo "Użycie: $0 [OPCJE]" + echo + echo "Opcje:" + echo " --show_active_output Wyświetl tylko sterowniki z aktywnymi wyjściami" + echo " --all Wyświetl pełne informacje o sterownikach" + echo " --help Wyświetl tę pomoc" + exit 1 +} + +# Jeśli nie podano żadnych argumentów, wyświetl pomoc +if [ $# -eq 0 ]; then + show_help +fi + +# Domyślne wartości parametrów +show_active_output=false # Domyślnie nie pokazujemy aktywnych wyjść +show_all=false # Domyślnie nie pokazujemy wszystkich informacji + +# Sprawdzenie, jakie parametry zostały podane +for arg in "$@"; do + case $arg in + --show_active_output) + show_active_output=true + shift + ;; + --all) + show_all=true + shift + ;; + --help) + show_help + shift + ;; + *) + echo "Nieznana opcja: $arg" + show_help + ;; + esac +done + +# Plik XML, z którego będziemy pobierać wartości Address +xml_file="ibvunit/ibvunit.xml" + +# Wyciągnięcie wartości Address tylko z sekcji +awk '//' "$xml_file" | grep -oP 'Address="\K\d+' | while read -r address; do + # Uruchomienie polecenia dla każdej wartości Address + output=$(./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.$address.out;);") + + # Jeśli parametr show_all jest ustawiony na 'true', pokaż pełne wyjście polecenia + if [ "$show_all" = true ]; then + echo "Sterownik id.$address:" + echo "$output" + fi + + # Jeśli parametr show_active_output jest ustawiony na 'true', wyświetl tylko sterowniki z włączonymi wyjściami + if [ "$show_active_output" = true ]; then + active_outputs=$(echo "$output" | grep -oP 'do\.\d+ = 1') + + if [ -n "$active_outputs" ]; then + echo "Sterownik id.$address ma aktywne wyjścia:" + echo "$active_outputs" | while read -r line; do + output_name=$(echo "$line" | cut -d' ' -f1) # wyciągnięcie nazwy wyjścia, np. do.0 + echo "Włączone wyjście: $output_name" + done + fi + fi +done + diff --git a/testowe/check_status1.py b/testowe/check_status1.py new file mode 100644 index 0000000..7ca8f94 --- /dev/null +++ b/testowe/check_status1.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Read dok.txt and create a mapping of output names to their descriptions +def load_output_descriptions(dok_file): + descriptions = {} + current_id = None + with open(dok_file, 'r') as file: + for line in file: + line = line.strip() + if line.startswith("id."): # New controller section + current_id = line.split(".")[1] + elif current_id is not None and line.startswith("output.do."): + output_name = f"rs.0.id.{current_id}.{line.split('=')[0].strip()}" + description = line.split('=')[1].strip() + descriptions[output_name] = description + return descriptions + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # Load output descriptions from dok.txt + output_descriptions = load_output_descriptions(dok_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., rs.0.id.39.output.do.2 + output_name = line.split('=')[0].strip() + output_identifier = output_name.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier.split('.')[-1]}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier.split('.')[-1]}" # Corrected to just 'output.do.x' + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + print(f"Controller id.{address} output.{output_identifier.split('.')[-1]} name: {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status2.py b/testowe/check_status2.py new file mode 100644 index 0000000..5556d58 --- /dev/null +++ b/testowe/check_status2.py @@ -0,0 +1,81 @@ +import argparse + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +def parse_arguments(): + parser = argparse.ArgumentParser(description="Controller output monitoring script.") + parser.add_argument('--all', action='store_true', help='Show all controller outputs.') + parser.add_argument('--show-active-output', action='store_true', help='Show only active outputs.') + parser.add_argument('--show-id', type=int, help='Show outputs for a specific controller ID.') + return parser.parse_args() + +def read_dok_file(dok_file): + output_descriptions = {} + controllers = {} + + with open(dok_file, 'r') as f: + lines = f.readlines() + current_id = None + for line in lines: + line = line.strip() + if line.startswith("id."): + current_id = line.split('.')[1] + controllers[current_id] = {'active_outputs': [], 'name': f'Controller {current_id}'} + elif current_id and "=" in line: + key, value = line.split("=") + output_key = key.strip() + output_descriptions[output_key] = value.strip() + # Check if the output key is an active output for the current controller + if output_key.startswith('output.do.'): + controllers[current_id]['active_outputs'].append(output_key) + + return output_descriptions, controllers + +def main(): + args = parse_arguments() + + # Read output descriptions from dok.txt and create controllers dictionary + output_descriptions, controllers = read_dok_file(dok_file) + + if not (args.all or args.show_active_output): + print("Error: You must provide either --all or --show-active-output.") + return + + for address, controller in controllers.items(): + if args.show_id is not None and int(address) != args.show_id: + continue + + if args.all: + print(f"{controller['name']}:") + for output in controller['active_outputs']: + description = output_descriptions.get(output, "Unknown output") + print(f"{output} name: {description}") + + if args.show_active_output: + active_outputs = controller['active_outputs'] + if active_outputs: + for line in active_outputs: + output_identifier = line.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier}" + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + # Change output to include the full output key + print(f"Controller id.{address} output.do.{output_identifier} - {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/desc_gen.py b/testowe/desc_gen.py new file mode 100644 index 0000000..95e1757 --- /dev/null +++ b/testowe/desc_gen.py @@ -0,0 +1,118 @@ +import re + +def load_device_list(file_path): + """Wczytuje listę urządzeń z pliku.""" + with open(file_path, 'r', encoding='utf-8') as file: + lines = [line.strip() for line in file if line.strip()] + return lines + +def parse_devices(lines): + """Grupuje urządzenia według ID, pomijając te, które już mają opis.""" + devices = {} + for line in lines: + if '-' in line: # Pomija urządzenia, które już mają opis + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id not in devices: + devices[device_id] = [] + devices[device_id].append(line) + return devices + +def load_existing_descriptions(file_path): + """Wczytuje istniejące opisy z pliku wynikowego.""" + try: + with open(file_path, 'r', encoding='utf-8') as file: + return {line.split(" - ")[0].strip(): line.strip() for line in file if " - " in line} + except FileNotFoundError: + return {} + +def generate_descriptions(devices, existing_descriptions): + """Interaktywnie generuje opisy dla urządzeń.""" + descriptions = {} + try: + for device_id, components in devices.items(): + print(f"\nID urządzenia: {device_id}") + # Generowanie opisu głównego urządzenia + if f"id {device_id}" in existing_descriptions: + current_desc = existing_descriptions[f"id {device_id}"] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input("Czy chcesz zmodyfikować ten opis? (tak/nie): ").strip().lower() + if modify == "nie": + continue + else: + description = input(f"Podaj nowy opis dla ID {device_id} (np. wiatrołap/kuchnia): ").strip() + if not description: + description = "brak" + descriptions[device_id] = {f"id {device_id}": description} + + # Generowanie opisów dla komponentów urządzenia + for component in components: + if component in existing_descriptions: + current_desc = existing_descriptions[component] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input(f"Czy chcesz zmodyfikować opis dla {component}? (tak/nie): ").strip().lower() + if modify == "nie": + continue + component_desc = input(f"Podaj opis dla {component}: ").strip() + if not component_desc: + component_desc = "brak" + descriptions.setdefault(device_id, {})[component] = component_desc + + except (KeyboardInterrupt, EOFError): # Obsługuje Ctrl+C i Ctrl+Z + print("\nZatrzymano interakcję. Zapisywanie danych...") + return descriptions, True + + return descriptions, False + +def save_descriptions(file_path, descriptions, original_lines, existing_descriptions): + """Zapisuje opisy do pliku, zachowując istniejącą strukturę.""" + with open(file_path, 'w', encoding='utf-8') as file: + for line in original_lines: + if '-' in line: + file.write(line + '\n') + continue + if line in existing_descriptions: + file.write(existing_descriptions[line] + '\n') + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id in descriptions and line in descriptions[device_id]: + file.write(f"{line} - {descriptions[device_id][line]}\n") + else: + file.write(line + '\n') + else: + file.write(line + '\n') + +def main(): + input_file = 'dok.txt' + output_file = 'dok_output.txt' + + print("Wczytywanie urządzeń i istniejących opisów...") + original_lines = load_device_list(input_file) + devices = parse_devices(original_lines) + existing_descriptions = load_existing_descriptions(output_file) + + if not devices: + print("Brak urządzeń do opisania.") + return + + print(f"Znaleziono {len(devices)} urządzeń do opisania.") + + all_descriptions = {} + while devices: + descriptions, should_exit = generate_descriptions(devices, existing_descriptions) + all_descriptions.update(descriptions) + if should_exit: + break + + print("\nZapisywanie opisów do pliku...") + save_descriptions(output_file, all_descriptions, original_lines, existing_descriptions) + print(f"Opisy zapisano w pliku {output_file}.") + print("Zakończono.") + +if __name__ == "__main__": + main() + diff --git a/testowe/dok.txt b/testowe/dok.txt new file mode 100644 index 0000000..8423487 --- /dev/null +++ b/testowe/dok.txt @@ -0,0 +1,239 @@ +id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +id 02 +rs.0.id.02.t.0 +rs.0.id.02.t.1 +rs.0.id.02.t.2 +rs.0.id.02.t.3 +rs.0.id.02.do.t.0 +rs.0.id.02.do.t.1 +rs.0.id.02.do.t.2 +rs.0.id.02.do.t.3 +rs.0.id.02.px0 +rs.0.id.02.px1 + +id 03 +rs.0.id.03.t.0 +rs.0.id.03.t.1 +rs.0.id.03.t.2 +rs.0.id.03.t.3 +rs.0.id.03.do.t.0 +rs.0.id.03.do.t.1 +rs.0.id.03.do.t.2 +rs.0.id.03.do.t.3 +rs.0.id.03.px0 +rs.0.id.03.px1 + +id 04 +rs.0.id.04.t.0 +rs.0.id.04.t.1 +rs.0.id.04.t.2 +rs.0.id.04.t.3 +rs.0.id.04.do.t.0 +rs.0.id.04.do.t.1 +rs.0.id.04.do.t.2 +rs.0.id.04.do.t.3 +rs.0.id.04.px0 +rs.0.id.04.px1 + +id 05 +rs.0.id.05.t.0 +rs.0.id.05.t.1 +rs.0.id.05.t.2 +rs.0.id.05.t.3 +rs.0.id.05.do.t.0 +rs.0.id.05.do.t.1 +rs.0.id.05.do.t.2 +rs.0.id.05.do.t.3 +rs.0.id.05.px0 +rs.0.id.05.px1 + +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oświetlenie H1 +rs.0.id.30.do.t.1 - Oświetlenie H2 +rs.0.id.30.do.t.2 - Oświetlenie K1, szynoprzewód +rs.0.id.30.do.t.3 - Oświetlenie K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak + +id 31 +rs.0.id.31.t.0 +rs.0.id.31.t.1 +rs.0.id.31.t.2 +rs.0.id.31.t.3 +rs.0.id.31.do.t.0 +rs.0.id.31.do.t.1 +rs.0.id.31.do.t.2 +rs.0.id.31.do.t.3 +rs.0.id.31.px0 +rs.0.id.31.px1 + +id 32 +rs.0.id.32.t.0 +rs.0.id.32.t.1 +rs.0.id.32.t.2 +rs.0.id.32.t.3 +rs.0.id.32.do.t.0 +rs.0.id.32.do.t.1 +rs.0.id.32.do.t.2 +rs.0.id.32.do.t.3 +rs.0.id.32.px0 +rs.0.id.32.px1 + +id 33 +rs.0.id.33.t.0 +rs.0.id.33.t.1 +rs.0.id.33.t.2 +rs.0.id.33.t.3 +rs.0.id.33.do.t.0 +rs.0.id.33.do.t.1 +rs.0.id.33.do.t.2 +rs.0.id.33.do.t.3 +rs.0.id.33.px0 +rs.0.id.33.px1 + +id 34 +rs.0.id.34.t.0 +rs.0.id.34.t.1 +rs.0.id.34.t.2 +rs.0.id.34.t.3 +rs.0.id.34.do.t.0 +rs.0.id.34.do.t.1 +rs.0.id.34.do.t.2 +rs.0.id.34.do.t.3 +rs.0.id.34.px0 +rs.0.id.34.px1 + +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 + +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 + +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 + +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 + +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 + +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 + +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 + +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 + +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 + +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/proj-ib-lighting-rs485-zarki.yaml b/proj-ib-lighting-rs485-zarki.yaml index 3a47859..214118d 100644 --- a/proj-ib-lighting-rs485-zarki.yaml +++ b/proj-ib-lighting-rs485-zarki.yaml @@ -278,7 +278,7 @@ - io_id: "input.t.1" status: "ok" mapping: "" - description: """ + description: "" - io_id: "input.t.2" status: "ok" mapping: "" diff --git a/testowe/check_perm.sh b/testowe/check_perm.sh new file mode 100755 index 0000000..a9f141e --- /dev/null +++ b/testowe/check_perm.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +chown -R root:root /ibsystem +chmod 755 /ibsystem/*.sh +chmod 755 /ibsystem/ibvunit/ibvunit +chmod 755 /ibsystem/ibmanager/ibmanager +chmod 755 /ibsystem/ibls diff --git a/testowe/check_status.py b/testowe/check_status.py new file mode 100644 index 0000000..6457cef --- /dev/null +++ b/testowe/check_status.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., do.x + output_name = line.split('=')[0].strip() + output_name = output_name.split('.')[-2] + '.' + output_name.split('.')[-1] # do.x + print(f"Active output: {output_name}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status.sh b/testowe/check_status.sh new file mode 100755 index 0000000..f0aa2ba --- /dev/null +++ b/testowe/check_status.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# Funkcja wyświetlająca pomoc +show_help() { + echo "Użycie: $0 [OPCJE]" + echo + echo "Opcje:" + echo " --show_active_output Wyświetl tylko sterowniki z aktywnymi wyjściami" + echo " --all Wyświetl pełne informacje o sterownikach" + echo " --help Wyświetl tę pomoc" + exit 1 +} + +# Jeśli nie podano żadnych argumentów, wyświetl pomoc +if [ $# -eq 0 ]; then + show_help +fi + +# Domyślne wartości parametrów +show_active_output=false # Domyślnie nie pokazujemy aktywnych wyjść +show_all=false # Domyślnie nie pokazujemy wszystkich informacji + +# Sprawdzenie, jakie parametry zostały podane +for arg in "$@"; do + case $arg in + --show_active_output) + show_active_output=true + shift + ;; + --all) + show_all=true + shift + ;; + --help) + show_help + shift + ;; + *) + echo "Nieznana opcja: $arg" + show_help + ;; + esac +done + +# Plik XML, z którego będziemy pobierać wartości Address +xml_file="ibvunit/ibvunit.xml" + +# Wyciągnięcie wartości Address tylko z sekcji +awk '//' "$xml_file" | grep -oP 'Address="\K\d+' | while read -r address; do + # Uruchomienie polecenia dla każdej wartości Address + output=$(./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.$address.out;);") + + # Jeśli parametr show_all jest ustawiony na 'true', pokaż pełne wyjście polecenia + if [ "$show_all" = true ]; then + echo "Sterownik id.$address:" + echo "$output" + fi + + # Jeśli parametr show_active_output jest ustawiony na 'true', wyświetl tylko sterowniki z włączonymi wyjściami + if [ "$show_active_output" = true ]; then + active_outputs=$(echo "$output" | grep -oP 'do\.\d+ = 1') + + if [ -n "$active_outputs" ]; then + echo "Sterownik id.$address ma aktywne wyjścia:" + echo "$active_outputs" | while read -r line; do + output_name=$(echo "$line" | cut -d' ' -f1) # wyciągnięcie nazwy wyjścia, np. do.0 + echo "Włączone wyjście: $output_name" + done + fi + fi +done + diff --git a/testowe/check_status1.py b/testowe/check_status1.py new file mode 100644 index 0000000..7ca8f94 --- /dev/null +++ b/testowe/check_status1.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Read dok.txt and create a mapping of output names to their descriptions +def load_output_descriptions(dok_file): + descriptions = {} + current_id = None + with open(dok_file, 'r') as file: + for line in file: + line = line.strip() + if line.startswith("id."): # New controller section + current_id = line.split(".")[1] + elif current_id is not None and line.startswith("output.do."): + output_name = f"rs.0.id.{current_id}.{line.split('=')[0].strip()}" + description = line.split('=')[1].strip() + descriptions[output_name] = description + return descriptions + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # Load output descriptions from dok.txt + output_descriptions = load_output_descriptions(dok_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., rs.0.id.39.output.do.2 + output_name = line.split('=')[0].strip() + output_identifier = output_name.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier.split('.')[-1]}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier.split('.')[-1]}" # Corrected to just 'output.do.x' + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + print(f"Controller id.{address} output.{output_identifier.split('.')[-1]} name: {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status2.py b/testowe/check_status2.py new file mode 100644 index 0000000..5556d58 --- /dev/null +++ b/testowe/check_status2.py @@ -0,0 +1,81 @@ +import argparse + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +def parse_arguments(): + parser = argparse.ArgumentParser(description="Controller output monitoring script.") + parser.add_argument('--all', action='store_true', help='Show all controller outputs.') + parser.add_argument('--show-active-output', action='store_true', help='Show only active outputs.') + parser.add_argument('--show-id', type=int, help='Show outputs for a specific controller ID.') + return parser.parse_args() + +def read_dok_file(dok_file): + output_descriptions = {} + controllers = {} + + with open(dok_file, 'r') as f: + lines = f.readlines() + current_id = None + for line in lines: + line = line.strip() + if line.startswith("id."): + current_id = line.split('.')[1] + controllers[current_id] = {'active_outputs': [], 'name': f'Controller {current_id}'} + elif current_id and "=" in line: + key, value = line.split("=") + output_key = key.strip() + output_descriptions[output_key] = value.strip() + # Check if the output key is an active output for the current controller + if output_key.startswith('output.do.'): + controllers[current_id]['active_outputs'].append(output_key) + + return output_descriptions, controllers + +def main(): + args = parse_arguments() + + # Read output descriptions from dok.txt and create controllers dictionary + output_descriptions, controllers = read_dok_file(dok_file) + + if not (args.all or args.show_active_output): + print("Error: You must provide either --all or --show-active-output.") + return + + for address, controller in controllers.items(): + if args.show_id is not None and int(address) != args.show_id: + continue + + if args.all: + print(f"{controller['name']}:") + for output in controller['active_outputs']: + description = output_descriptions.get(output, "Unknown output") + print(f"{output} name: {description}") + + if args.show_active_output: + active_outputs = controller['active_outputs'] + if active_outputs: + for line in active_outputs: + output_identifier = line.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier}" + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + # Change output to include the full output key + print(f"Controller id.{address} output.do.{output_identifier} - {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/desc_gen.py b/testowe/desc_gen.py new file mode 100644 index 0000000..95e1757 --- /dev/null +++ b/testowe/desc_gen.py @@ -0,0 +1,118 @@ +import re + +def load_device_list(file_path): + """Wczytuje listę urządzeń z pliku.""" + with open(file_path, 'r', encoding='utf-8') as file: + lines = [line.strip() for line in file if line.strip()] + return lines + +def parse_devices(lines): + """Grupuje urządzenia według ID, pomijając te, które już mają opis.""" + devices = {} + for line in lines: + if '-' in line: # Pomija urządzenia, które już mają opis + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id not in devices: + devices[device_id] = [] + devices[device_id].append(line) + return devices + +def load_existing_descriptions(file_path): + """Wczytuje istniejące opisy z pliku wynikowego.""" + try: + with open(file_path, 'r', encoding='utf-8') as file: + return {line.split(" - ")[0].strip(): line.strip() for line in file if " - " in line} + except FileNotFoundError: + return {} + +def generate_descriptions(devices, existing_descriptions): + """Interaktywnie generuje opisy dla urządzeń.""" + descriptions = {} + try: + for device_id, components in devices.items(): + print(f"\nID urządzenia: {device_id}") + # Generowanie opisu głównego urządzenia + if f"id {device_id}" in existing_descriptions: + current_desc = existing_descriptions[f"id {device_id}"] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input("Czy chcesz zmodyfikować ten opis? (tak/nie): ").strip().lower() + if modify == "nie": + continue + else: + description = input(f"Podaj nowy opis dla ID {device_id} (np. wiatrołap/kuchnia): ").strip() + if not description: + description = "brak" + descriptions[device_id] = {f"id {device_id}": description} + + # Generowanie opisów dla komponentów urządzenia + for component in components: + if component in existing_descriptions: + current_desc = existing_descriptions[component] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input(f"Czy chcesz zmodyfikować opis dla {component}? (tak/nie): ").strip().lower() + if modify == "nie": + continue + component_desc = input(f"Podaj opis dla {component}: ").strip() + if not component_desc: + component_desc = "brak" + descriptions.setdefault(device_id, {})[component] = component_desc + + except (KeyboardInterrupt, EOFError): # Obsługuje Ctrl+C i Ctrl+Z + print("\nZatrzymano interakcję. Zapisywanie danych...") + return descriptions, True + + return descriptions, False + +def save_descriptions(file_path, descriptions, original_lines, existing_descriptions): + """Zapisuje opisy do pliku, zachowując istniejącą strukturę.""" + with open(file_path, 'w', encoding='utf-8') as file: + for line in original_lines: + if '-' in line: + file.write(line + '\n') + continue + if line in existing_descriptions: + file.write(existing_descriptions[line] + '\n') + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id in descriptions and line in descriptions[device_id]: + file.write(f"{line} - {descriptions[device_id][line]}\n") + else: + file.write(line + '\n') + else: + file.write(line + '\n') + +def main(): + input_file = 'dok.txt' + output_file = 'dok_output.txt' + + print("Wczytywanie urządzeń i istniejących opisów...") + original_lines = load_device_list(input_file) + devices = parse_devices(original_lines) + existing_descriptions = load_existing_descriptions(output_file) + + if not devices: + print("Brak urządzeń do opisania.") + return + + print(f"Znaleziono {len(devices)} urządzeń do opisania.") + + all_descriptions = {} + while devices: + descriptions, should_exit = generate_descriptions(devices, existing_descriptions) + all_descriptions.update(descriptions) + if should_exit: + break + + print("\nZapisywanie opisów do pliku...") + save_descriptions(output_file, all_descriptions, original_lines, existing_descriptions) + print(f"Opisy zapisano w pliku {output_file}.") + print("Zakończono.") + +if __name__ == "__main__": + main() + diff --git a/testowe/dok.txt b/testowe/dok.txt new file mode 100644 index 0000000..8423487 --- /dev/null +++ b/testowe/dok.txt @@ -0,0 +1,239 @@ +id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +id 02 +rs.0.id.02.t.0 +rs.0.id.02.t.1 +rs.0.id.02.t.2 +rs.0.id.02.t.3 +rs.0.id.02.do.t.0 +rs.0.id.02.do.t.1 +rs.0.id.02.do.t.2 +rs.0.id.02.do.t.3 +rs.0.id.02.px0 +rs.0.id.02.px1 + +id 03 +rs.0.id.03.t.0 +rs.0.id.03.t.1 +rs.0.id.03.t.2 +rs.0.id.03.t.3 +rs.0.id.03.do.t.0 +rs.0.id.03.do.t.1 +rs.0.id.03.do.t.2 +rs.0.id.03.do.t.3 +rs.0.id.03.px0 +rs.0.id.03.px1 + +id 04 +rs.0.id.04.t.0 +rs.0.id.04.t.1 +rs.0.id.04.t.2 +rs.0.id.04.t.3 +rs.0.id.04.do.t.0 +rs.0.id.04.do.t.1 +rs.0.id.04.do.t.2 +rs.0.id.04.do.t.3 +rs.0.id.04.px0 +rs.0.id.04.px1 + +id 05 +rs.0.id.05.t.0 +rs.0.id.05.t.1 +rs.0.id.05.t.2 +rs.0.id.05.t.3 +rs.0.id.05.do.t.0 +rs.0.id.05.do.t.1 +rs.0.id.05.do.t.2 +rs.0.id.05.do.t.3 +rs.0.id.05.px0 +rs.0.id.05.px1 + +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oświetlenie H1 +rs.0.id.30.do.t.1 - Oświetlenie H2 +rs.0.id.30.do.t.2 - Oświetlenie K1, szynoprzewód +rs.0.id.30.do.t.3 - Oświetlenie K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak + +id 31 +rs.0.id.31.t.0 +rs.0.id.31.t.1 +rs.0.id.31.t.2 +rs.0.id.31.t.3 +rs.0.id.31.do.t.0 +rs.0.id.31.do.t.1 +rs.0.id.31.do.t.2 +rs.0.id.31.do.t.3 +rs.0.id.31.px0 +rs.0.id.31.px1 + +id 32 +rs.0.id.32.t.0 +rs.0.id.32.t.1 +rs.0.id.32.t.2 +rs.0.id.32.t.3 +rs.0.id.32.do.t.0 +rs.0.id.32.do.t.1 +rs.0.id.32.do.t.2 +rs.0.id.32.do.t.3 +rs.0.id.32.px0 +rs.0.id.32.px1 + +id 33 +rs.0.id.33.t.0 +rs.0.id.33.t.1 +rs.0.id.33.t.2 +rs.0.id.33.t.3 +rs.0.id.33.do.t.0 +rs.0.id.33.do.t.1 +rs.0.id.33.do.t.2 +rs.0.id.33.do.t.3 +rs.0.id.33.px0 +rs.0.id.33.px1 + +id 34 +rs.0.id.34.t.0 +rs.0.id.34.t.1 +rs.0.id.34.t.2 +rs.0.id.34.t.3 +rs.0.id.34.do.t.0 +rs.0.id.34.do.t.1 +rs.0.id.34.do.t.2 +rs.0.id.34.do.t.3 +rs.0.id.34.px0 +rs.0.id.34.px1 + +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 + +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 + +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 + +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 + +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 + +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 + +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 + +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 + +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 + +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/testowe/dok_back.txt b/testowe/dok_back.txt new file mode 100644 index 0000000..8ccd2ec --- /dev/null +++ b/testowe/dok_back.txt @@ -0,0 +1,258 @@ +id.39id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +px.0 = empty +px.1 = empty +output.do.0 = oświetlenie główne +output.do.1 = halogeny nad biurkiem +output.do.2 = chmurka +output.do.3 = kinkiet koło łóżka + +id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +id 02 +rs.0.id.02.t.0 +rs.0.id.02.t.1 +rs.0.id.02.t.2 +rs.0.id.02.t.3 +rs.0.id.02.do.t.0 +rs.0.id.02.do.t.1 +rs.0.id.02.do.t.2 +rs.0.id.02.do.t.3 +rs.0.id.02.px0 +rs.0.id.02.px1 + +id 03 +rs.0.id.03.t.0 +rs.0.id.03.t.1 +rs.0.id.03.t.2 +rs.0.id.03.t.3 +rs.0.id.03.do.t.0 +rs.0.id.03.do.t.1 +rs.0.id.03.do.t.2 +rs.0.id.03.do.t.3 +rs.0.id.03.px0 +rs.0.id.03.px1 + +id 04 +rs.0.id.04.t.0 +rs.0.id.04.t.1 +rs.0.id.04.t.2 +rs.0.id.04.t.3 +rs.0.id.04.do.t.0 +rs.0.id.04.do.t.1 +rs.0.id.04.do.t.2 +rs.0.id.04.do.t.3 +rs.0.id.04.px0 +rs.0.id.04.px1 + +id 05 +rs.0.id.05.t.0 +rs.0.id.05.t.1 +rs.0.id.05.t.2 +rs.0.id.05.t.3 +rs.0.id.05.do.t.0 +rs.0.id.05.do.t.1 +rs.0.id.05.do.t.2 +rs.0.id.05.do.t.3 +rs.0.id.05.px0 +rs.0.id.05.px1 + +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oświetlenie H1 +rs.0.id.30.do.t.1 - Oświetlenie H2 +rs.0.id.30.do.t.2 - Oświetlenie K1, szynoprzewód +rs.0.id.30.do.t.3 - Oświetlenie K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak + +id 31 +rs.0.id.31.t.0 +rs.0.id.31.t.1 +rs.0.id.31.t.2 +rs.0.id.31.t.3 +rs.0.id.31.do.t.0 +rs.0.id.31.do.t.1 +rs.0.id.31.do.t.2 +rs.0.id.31.do.t.3 +rs.0.id.31.px0 +rs.0.id.31.px1 + +id 32 +rs.0.id.32.t.0 +rs.0.id.32.t.1 +rs.0.id.32.t.2 +rs.0.id.32.t.3 +rs.0.id.32.do.t.0 +rs.0.id.32.do.t.1 +rs.0.id.32.do.t.2 +rs.0.id.32.do.t.3 +rs.0.id.32.px0 +rs.0.id.32.px1 + +id 33 +rs.0.id.33.t.0 +rs.0.id.33.t.1 +rs.0.id.33.t.2 +rs.0.id.33.t.3 +rs.0.id.33.do.t.0 +rs.0.id.33.do.t.1 +rs.0.id.33.do.t.2 +rs.0.id.33.do.t.3 +rs.0.id.33.px0 +rs.0.id.33.px1 + +id 34 +rs.0.id.34.t.0 +rs.0.id.34.t.1 +rs.0.id.34.t.2 +rs.0.id.34.t.3 +rs.0.id.34.do.t.0 +rs.0.id.34.do.t.1 +rs.0.id.34.do.t.2 +rs.0.id.34.do.t.3 +rs.0.id.34.px0 +rs.0.id.34.px1 + +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 + +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 + +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 + +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 + +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 + +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 + +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 + +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 + +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 + +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/proj-ib-lighting-rs485-zarki.yaml b/proj-ib-lighting-rs485-zarki.yaml index 3a47859..214118d 100644 --- a/proj-ib-lighting-rs485-zarki.yaml +++ b/proj-ib-lighting-rs485-zarki.yaml @@ -278,7 +278,7 @@ - io_id: "input.t.1" status: "ok" mapping: "" - description: """ + description: "" - io_id: "input.t.2" status: "ok" mapping: "" diff --git a/testowe/check_perm.sh b/testowe/check_perm.sh new file mode 100755 index 0000000..a9f141e --- /dev/null +++ b/testowe/check_perm.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +chown -R root:root /ibsystem +chmod 755 /ibsystem/*.sh +chmod 755 /ibsystem/ibvunit/ibvunit +chmod 755 /ibsystem/ibmanager/ibmanager +chmod 755 /ibsystem/ibls diff --git a/testowe/check_status.py b/testowe/check_status.py new file mode 100644 index 0000000..6457cef --- /dev/null +++ b/testowe/check_status.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., do.x + output_name = line.split('=')[0].strip() + output_name = output_name.split('.')[-2] + '.' + output_name.split('.')[-1] # do.x + print(f"Active output: {output_name}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status.sh b/testowe/check_status.sh new file mode 100755 index 0000000..f0aa2ba --- /dev/null +++ b/testowe/check_status.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# Funkcja wyświetlająca pomoc +show_help() { + echo "Użycie: $0 [OPCJE]" + echo + echo "Opcje:" + echo " --show_active_output Wyświetl tylko sterowniki z aktywnymi wyjściami" + echo " --all Wyświetl pełne informacje o sterownikach" + echo " --help Wyświetl tę pomoc" + exit 1 +} + +# Jeśli nie podano żadnych argumentów, wyświetl pomoc +if [ $# -eq 0 ]; then + show_help +fi + +# Domyślne wartości parametrów +show_active_output=false # Domyślnie nie pokazujemy aktywnych wyjść +show_all=false # Domyślnie nie pokazujemy wszystkich informacji + +# Sprawdzenie, jakie parametry zostały podane +for arg in "$@"; do + case $arg in + --show_active_output) + show_active_output=true + shift + ;; + --all) + show_all=true + shift + ;; + --help) + show_help + shift + ;; + *) + echo "Nieznana opcja: $arg" + show_help + ;; + esac +done + +# Plik XML, z którego będziemy pobierać wartości Address +xml_file="ibvunit/ibvunit.xml" + +# Wyciągnięcie wartości Address tylko z sekcji +awk '//' "$xml_file" | grep -oP 'Address="\K\d+' | while read -r address; do + # Uruchomienie polecenia dla każdej wartości Address + output=$(./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.$address.out;);") + + # Jeśli parametr show_all jest ustawiony na 'true', pokaż pełne wyjście polecenia + if [ "$show_all" = true ]; then + echo "Sterownik id.$address:" + echo "$output" + fi + + # Jeśli parametr show_active_output jest ustawiony na 'true', wyświetl tylko sterowniki z włączonymi wyjściami + if [ "$show_active_output" = true ]; then + active_outputs=$(echo "$output" | grep -oP 'do\.\d+ = 1') + + if [ -n "$active_outputs" ]; then + echo "Sterownik id.$address ma aktywne wyjścia:" + echo "$active_outputs" | while read -r line; do + output_name=$(echo "$line" | cut -d' ' -f1) # wyciągnięcie nazwy wyjścia, np. do.0 + echo "Włączone wyjście: $output_name" + done + fi + fi +done + diff --git a/testowe/check_status1.py b/testowe/check_status1.py new file mode 100644 index 0000000..7ca8f94 --- /dev/null +++ b/testowe/check_status1.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Read dok.txt and create a mapping of output names to their descriptions +def load_output_descriptions(dok_file): + descriptions = {} + current_id = None + with open(dok_file, 'r') as file: + for line in file: + line = line.strip() + if line.startswith("id."): # New controller section + current_id = line.split(".")[1] + elif current_id is not None and line.startswith("output.do."): + output_name = f"rs.0.id.{current_id}.{line.split('=')[0].strip()}" + description = line.split('=')[1].strip() + descriptions[output_name] = description + return descriptions + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # Load output descriptions from dok.txt + output_descriptions = load_output_descriptions(dok_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., rs.0.id.39.output.do.2 + output_name = line.split('=')[0].strip() + output_identifier = output_name.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier.split('.')[-1]}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier.split('.')[-1]}" # Corrected to just 'output.do.x' + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + print(f"Controller id.{address} output.{output_identifier.split('.')[-1]} name: {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status2.py b/testowe/check_status2.py new file mode 100644 index 0000000..5556d58 --- /dev/null +++ b/testowe/check_status2.py @@ -0,0 +1,81 @@ +import argparse + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +def parse_arguments(): + parser = argparse.ArgumentParser(description="Controller output monitoring script.") + parser.add_argument('--all', action='store_true', help='Show all controller outputs.') + parser.add_argument('--show-active-output', action='store_true', help='Show only active outputs.') + parser.add_argument('--show-id', type=int, help='Show outputs for a specific controller ID.') + return parser.parse_args() + +def read_dok_file(dok_file): + output_descriptions = {} + controllers = {} + + with open(dok_file, 'r') as f: + lines = f.readlines() + current_id = None + for line in lines: + line = line.strip() + if line.startswith("id."): + current_id = line.split('.')[1] + controllers[current_id] = {'active_outputs': [], 'name': f'Controller {current_id}'} + elif current_id and "=" in line: + key, value = line.split("=") + output_key = key.strip() + output_descriptions[output_key] = value.strip() + # Check if the output key is an active output for the current controller + if output_key.startswith('output.do.'): + controllers[current_id]['active_outputs'].append(output_key) + + return output_descriptions, controllers + +def main(): + args = parse_arguments() + + # Read output descriptions from dok.txt and create controllers dictionary + output_descriptions, controllers = read_dok_file(dok_file) + + if not (args.all or args.show_active_output): + print("Error: You must provide either --all or --show-active-output.") + return + + for address, controller in controllers.items(): + if args.show_id is not None and int(address) != args.show_id: + continue + + if args.all: + print(f"{controller['name']}:") + for output in controller['active_outputs']: + description = output_descriptions.get(output, "Unknown output") + print(f"{output} name: {description}") + + if args.show_active_output: + active_outputs = controller['active_outputs'] + if active_outputs: + for line in active_outputs: + output_identifier = line.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier}" + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + # Change output to include the full output key + print(f"Controller id.{address} output.do.{output_identifier} - {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/desc_gen.py b/testowe/desc_gen.py new file mode 100644 index 0000000..95e1757 --- /dev/null +++ b/testowe/desc_gen.py @@ -0,0 +1,118 @@ +import re + +def load_device_list(file_path): + """Wczytuje listę urządzeń z pliku.""" + with open(file_path, 'r', encoding='utf-8') as file: + lines = [line.strip() for line in file if line.strip()] + return lines + +def parse_devices(lines): + """Grupuje urządzenia według ID, pomijając te, które już mają opis.""" + devices = {} + for line in lines: + if '-' in line: # Pomija urządzenia, które już mają opis + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id not in devices: + devices[device_id] = [] + devices[device_id].append(line) + return devices + +def load_existing_descriptions(file_path): + """Wczytuje istniejące opisy z pliku wynikowego.""" + try: + with open(file_path, 'r', encoding='utf-8') as file: + return {line.split(" - ")[0].strip(): line.strip() for line in file if " - " in line} + except FileNotFoundError: + return {} + +def generate_descriptions(devices, existing_descriptions): + """Interaktywnie generuje opisy dla urządzeń.""" + descriptions = {} + try: + for device_id, components in devices.items(): + print(f"\nID urządzenia: {device_id}") + # Generowanie opisu głównego urządzenia + if f"id {device_id}" in existing_descriptions: + current_desc = existing_descriptions[f"id {device_id}"] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input("Czy chcesz zmodyfikować ten opis? (tak/nie): ").strip().lower() + if modify == "nie": + continue + else: + description = input(f"Podaj nowy opis dla ID {device_id} (np. wiatrołap/kuchnia): ").strip() + if not description: + description = "brak" + descriptions[device_id] = {f"id {device_id}": description} + + # Generowanie opisów dla komponentów urządzenia + for component in components: + if component in existing_descriptions: + current_desc = existing_descriptions[component] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input(f"Czy chcesz zmodyfikować opis dla {component}? (tak/nie): ").strip().lower() + if modify == "nie": + continue + component_desc = input(f"Podaj opis dla {component}: ").strip() + if not component_desc: + component_desc = "brak" + descriptions.setdefault(device_id, {})[component] = component_desc + + except (KeyboardInterrupt, EOFError): # Obsługuje Ctrl+C i Ctrl+Z + print("\nZatrzymano interakcję. Zapisywanie danych...") + return descriptions, True + + return descriptions, False + +def save_descriptions(file_path, descriptions, original_lines, existing_descriptions): + """Zapisuje opisy do pliku, zachowując istniejącą strukturę.""" + with open(file_path, 'w', encoding='utf-8') as file: + for line in original_lines: + if '-' in line: + file.write(line + '\n') + continue + if line in existing_descriptions: + file.write(existing_descriptions[line] + '\n') + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id in descriptions and line in descriptions[device_id]: + file.write(f"{line} - {descriptions[device_id][line]}\n") + else: + file.write(line + '\n') + else: + file.write(line + '\n') + +def main(): + input_file = 'dok.txt' + output_file = 'dok_output.txt' + + print("Wczytywanie urządzeń i istniejących opisów...") + original_lines = load_device_list(input_file) + devices = parse_devices(original_lines) + existing_descriptions = load_existing_descriptions(output_file) + + if not devices: + print("Brak urządzeń do opisania.") + return + + print(f"Znaleziono {len(devices)} urządzeń do opisania.") + + all_descriptions = {} + while devices: + descriptions, should_exit = generate_descriptions(devices, existing_descriptions) + all_descriptions.update(descriptions) + if should_exit: + break + + print("\nZapisywanie opisów do pliku...") + save_descriptions(output_file, all_descriptions, original_lines, existing_descriptions) + print(f"Opisy zapisano w pliku {output_file}.") + print("Zakończono.") + +if __name__ == "__main__": + main() + diff --git a/testowe/dok.txt b/testowe/dok.txt new file mode 100644 index 0000000..8423487 --- /dev/null +++ b/testowe/dok.txt @@ -0,0 +1,239 @@ +id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +id 02 +rs.0.id.02.t.0 +rs.0.id.02.t.1 +rs.0.id.02.t.2 +rs.0.id.02.t.3 +rs.0.id.02.do.t.0 +rs.0.id.02.do.t.1 +rs.0.id.02.do.t.2 +rs.0.id.02.do.t.3 +rs.0.id.02.px0 +rs.0.id.02.px1 + +id 03 +rs.0.id.03.t.0 +rs.0.id.03.t.1 +rs.0.id.03.t.2 +rs.0.id.03.t.3 +rs.0.id.03.do.t.0 +rs.0.id.03.do.t.1 +rs.0.id.03.do.t.2 +rs.0.id.03.do.t.3 +rs.0.id.03.px0 +rs.0.id.03.px1 + +id 04 +rs.0.id.04.t.0 +rs.0.id.04.t.1 +rs.0.id.04.t.2 +rs.0.id.04.t.3 +rs.0.id.04.do.t.0 +rs.0.id.04.do.t.1 +rs.0.id.04.do.t.2 +rs.0.id.04.do.t.3 +rs.0.id.04.px0 +rs.0.id.04.px1 + +id 05 +rs.0.id.05.t.0 +rs.0.id.05.t.1 +rs.0.id.05.t.2 +rs.0.id.05.t.3 +rs.0.id.05.do.t.0 +rs.0.id.05.do.t.1 +rs.0.id.05.do.t.2 +rs.0.id.05.do.t.3 +rs.0.id.05.px0 +rs.0.id.05.px1 + +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oświetlenie H1 +rs.0.id.30.do.t.1 - Oświetlenie H2 +rs.0.id.30.do.t.2 - Oświetlenie K1, szynoprzewód +rs.0.id.30.do.t.3 - Oświetlenie K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak + +id 31 +rs.0.id.31.t.0 +rs.0.id.31.t.1 +rs.0.id.31.t.2 +rs.0.id.31.t.3 +rs.0.id.31.do.t.0 +rs.0.id.31.do.t.1 +rs.0.id.31.do.t.2 +rs.0.id.31.do.t.3 +rs.0.id.31.px0 +rs.0.id.31.px1 + +id 32 +rs.0.id.32.t.0 +rs.0.id.32.t.1 +rs.0.id.32.t.2 +rs.0.id.32.t.3 +rs.0.id.32.do.t.0 +rs.0.id.32.do.t.1 +rs.0.id.32.do.t.2 +rs.0.id.32.do.t.3 +rs.0.id.32.px0 +rs.0.id.32.px1 + +id 33 +rs.0.id.33.t.0 +rs.0.id.33.t.1 +rs.0.id.33.t.2 +rs.0.id.33.t.3 +rs.0.id.33.do.t.0 +rs.0.id.33.do.t.1 +rs.0.id.33.do.t.2 +rs.0.id.33.do.t.3 +rs.0.id.33.px0 +rs.0.id.33.px1 + +id 34 +rs.0.id.34.t.0 +rs.0.id.34.t.1 +rs.0.id.34.t.2 +rs.0.id.34.t.3 +rs.0.id.34.do.t.0 +rs.0.id.34.do.t.1 +rs.0.id.34.do.t.2 +rs.0.id.34.do.t.3 +rs.0.id.34.px0 +rs.0.id.34.px1 + +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 + +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 + +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 + +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 + +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 + +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 + +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 + +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 + +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 + +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/testowe/dok_back.txt b/testowe/dok_back.txt new file mode 100644 index 0000000..8ccd2ec --- /dev/null +++ b/testowe/dok_back.txt @@ -0,0 +1,258 @@ +id.39id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +px.0 = empty +px.1 = empty +output.do.0 = oświetlenie główne +output.do.1 = halogeny nad biurkiem +output.do.2 = chmurka +output.do.3 = kinkiet koło łóżka + +id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +id 02 +rs.0.id.02.t.0 +rs.0.id.02.t.1 +rs.0.id.02.t.2 +rs.0.id.02.t.3 +rs.0.id.02.do.t.0 +rs.0.id.02.do.t.1 +rs.0.id.02.do.t.2 +rs.0.id.02.do.t.3 +rs.0.id.02.px0 +rs.0.id.02.px1 + +id 03 +rs.0.id.03.t.0 +rs.0.id.03.t.1 +rs.0.id.03.t.2 +rs.0.id.03.t.3 +rs.0.id.03.do.t.0 +rs.0.id.03.do.t.1 +rs.0.id.03.do.t.2 +rs.0.id.03.do.t.3 +rs.0.id.03.px0 +rs.0.id.03.px1 + +id 04 +rs.0.id.04.t.0 +rs.0.id.04.t.1 +rs.0.id.04.t.2 +rs.0.id.04.t.3 +rs.0.id.04.do.t.0 +rs.0.id.04.do.t.1 +rs.0.id.04.do.t.2 +rs.0.id.04.do.t.3 +rs.0.id.04.px0 +rs.0.id.04.px1 + +id 05 +rs.0.id.05.t.0 +rs.0.id.05.t.1 +rs.0.id.05.t.2 +rs.0.id.05.t.3 +rs.0.id.05.do.t.0 +rs.0.id.05.do.t.1 +rs.0.id.05.do.t.2 +rs.0.id.05.do.t.3 +rs.0.id.05.px0 +rs.0.id.05.px1 + +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oświetlenie H1 +rs.0.id.30.do.t.1 - Oświetlenie H2 +rs.0.id.30.do.t.2 - Oświetlenie K1, szynoprzewód +rs.0.id.30.do.t.3 - Oświetlenie K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak + +id 31 +rs.0.id.31.t.0 +rs.0.id.31.t.1 +rs.0.id.31.t.2 +rs.0.id.31.t.3 +rs.0.id.31.do.t.0 +rs.0.id.31.do.t.1 +rs.0.id.31.do.t.2 +rs.0.id.31.do.t.3 +rs.0.id.31.px0 +rs.0.id.31.px1 + +id 32 +rs.0.id.32.t.0 +rs.0.id.32.t.1 +rs.0.id.32.t.2 +rs.0.id.32.t.3 +rs.0.id.32.do.t.0 +rs.0.id.32.do.t.1 +rs.0.id.32.do.t.2 +rs.0.id.32.do.t.3 +rs.0.id.32.px0 +rs.0.id.32.px1 + +id 33 +rs.0.id.33.t.0 +rs.0.id.33.t.1 +rs.0.id.33.t.2 +rs.0.id.33.t.3 +rs.0.id.33.do.t.0 +rs.0.id.33.do.t.1 +rs.0.id.33.do.t.2 +rs.0.id.33.do.t.3 +rs.0.id.33.px0 +rs.0.id.33.px1 + +id 34 +rs.0.id.34.t.0 +rs.0.id.34.t.1 +rs.0.id.34.t.2 +rs.0.id.34.t.3 +rs.0.id.34.do.t.0 +rs.0.id.34.do.t.1 +rs.0.id.34.do.t.2 +rs.0.id.34.do.t.3 +rs.0.id.34.px0 +rs.0.id.34.px1 + +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 + +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 + +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 + +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 + +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 + +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 + +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 + +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 + +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 + +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/testowe/dok_output.txt b/testowe/dok_output.txt new file mode 100644 index 0000000..6c98aa8 --- /dev/null +++ b/testowe/dok_output.txt @@ -0,0 +1,220 @@ +id 01 +rs.0.id.01.t.0 - czujnik temperatury wymiennika na kominku +rs.0.id.01.t.1 - brak +rs.0.id.01.t.2 - brak +rs.0.id.01.t.3 - brak +rs.0.id.01.do.t.0 - pompa kominka +rs.0.id.01.do.t.1 - brak +rs.0.id.01.do.t.2 - brak +rs.0.id.01.do.t.3 - brak +rs.0.id.01.px0 - brak +rs.0.id.01.px1 - brak +id 02 +rs.0.id.02.t.0 - brak +rs.0.id.02.t.1 - brak +rs.0.id.02.t.2 - brak +rs.0.id.02.t.3 - brak +rs.0.id.02.do.t.0 - brak +rs.0.id.02.do.t.1 - brak +rs.0.id.02.do.t.2 - brak +rs.0.id.02.do.t.3 - brak +rs.0.id.02.px0 - brak +rs.0.id.02.px1 - brak +id 03 +rs.0.id.03.t.0 - brak +rs.0.id.03.t.1 - brak +rs.0.id.03.t.2 - brak +rs.0.id.03.t.3 - brak +rs.0.id.03.do.t.0 - brak +rs.0.id.03.do.t.1 - brak +rs.0.id.03.do.t.2 - brak +rs.0.id.03.do.t.3 - brak +rs.0.id.03.px0 - brak +rs.0.id.03.px1 - brak +id 04 +rs.0.id.04.t.0 - brak +rs.0.id.04.t.1 - brak +rs.0.id.04.t.2 - brak +rs.0.id.04.t.3 - brak +rs.0.id.04.do.t.0 - brak +rs.0.id.04.do.t.1 - brak +rs.0.id.04.do.t.2 - brak +rs.0.id.04.do.t.3 - brak +rs.0.id.04.px0 - brak +rs.0.id.04.px1 - brak +id 05 +rs.0.id.05.t.0 - brak +rs.0.id.05.t.1 - brak +rs.0.id.05.t.2 - brak +rs.0.id.05.t.3 - brak +rs.0.id.05.do.t.0 - brak +rs.0.id.05.do.t.1 - brak +rs.0.id.05.do.t.2 - brak +rs.0.id.05.do.t.3 - brak +rs.0.id.05.px0 - brak +rs.0.id.05.px1 - brak +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oś H1 +rs.0.id.30.do.t.1 - Oś H2 +rs.0.id.30.do.t.2 - Oś K1, szynoprzewód +rs.0.id.30.do.t.3 - Oś K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak +id 31 +rs.0.id.31.t.0 - przycisk K3, zug 5 +rs.0.id.31.t.1 - przycisk K4, zug 7 +rs.0.id.31.t.2 - przycisk K5 +rs.0.id.31.t.3 - przycisk K6 +rs.0.id.31.do.t.0 - Oś K3, halogeny okno +rs.0.id.31.do.t.1 - Oś K4, lampy nad barem +rs.0.id.31.do.t.2 - Oś K5, ledy pod półkami +rs.0.id.31.do.t.3 - Os K6, led okno +rs.0.id.31.px0 - brak +rs.0.id.31.px1 - brak +id 32 +rs.0.id.32.t.0 - przycisk J1, zug 14, J1 czarny +rs.0.id.32.t.1 - przycisk J2, zug 14,J2 brazowy +rs.0.id.32.t.2 - przycisk S1, zug 10, S1 czarny +rs.0.id.32.t.3 - przycisk S5, zug 10, S5 brazowy +rs.0.id.32.do.t.0 - Oś J1, Nad stołem +rs.0.id.32.do.t.1 - Oś J2, Nad stołem # połączone razem J1 i J2 +rs.0.id.32.do.t.2 - Oś S1, Ring salon +rs.0.id.32.do.t.3 - oś S5, led dekoracyjny koło kanapy +rs.0.id.32.px0 - brak +rs.0.id.32.px1 - brak +id 33 +rs.0.id.33.t.0 - przycisk S2, zug 11 +rs.0.id.33.t.1 - przycisk S3, zug 11 +rs.0.id.33.t.2 - przycisk S4 +rs.0.id.33.t.3 - przycisk S6 +rs.0.id.33.do.t.0 - Oś S2, spotlight za kanapom +rs.0.id.33.do.t.1 - Oś S3, spotlight przed TV +rs.0.id.33.do.t.2 - Oś S4, Led TV +rs.0.id.33.do.t.3 - Oś S6, Led sufit wnęka, przewód 4.4, zug 13 +rs.0.id.33.px0 - brak +rs.0.id.33.px1 - brak +id 34 +rs.0.id.34.t.0 - przycisk H3, zug 16, szyno przewód +rs.0.id.34.t.1 - przycisk H4, zug 16, szyno przewód +rs.0.id.34.t.2 - przycisk H5 +rs.0.id.34.t.3 - przycisk H6 +rs.0.id.34.do.t.0 - Oś H3, szyno przewód +rs.0.id.34.do.t.1 - Oś H4, szyno przewód +rs.0.id.34.do.t.2 - Oś H5, zug 17, przedów 5.2 Ledy pionowe +rs.0.id.34.do.t.3 - Oś H6, zug 18, przewód 5.3 Led kominek #Brazowy 230v gniazdo kominek, niebieski N, Żółty 230V zasilacz Led kominek +rs.0.id.34.px0 - brak +rs.0.id.34.px1 - brak +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/proj-ib-lighting-rs485-zarki.yaml b/proj-ib-lighting-rs485-zarki.yaml index 3a47859..214118d 100644 --- a/proj-ib-lighting-rs485-zarki.yaml +++ b/proj-ib-lighting-rs485-zarki.yaml @@ -278,7 +278,7 @@ - io_id: "input.t.1" status: "ok" mapping: "" - description: """ + description: "" - io_id: "input.t.2" status: "ok" mapping: "" diff --git a/testowe/check_perm.sh b/testowe/check_perm.sh new file mode 100755 index 0000000..a9f141e --- /dev/null +++ b/testowe/check_perm.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +chown -R root:root /ibsystem +chmod 755 /ibsystem/*.sh +chmod 755 /ibsystem/ibvunit/ibvunit +chmod 755 /ibsystem/ibmanager/ibmanager +chmod 755 /ibsystem/ibls diff --git a/testowe/check_status.py b/testowe/check_status.py new file mode 100644 index 0000000..6457cef --- /dev/null +++ b/testowe/check_status.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., do.x + output_name = line.split('=')[0].strip() + output_name = output_name.split('.')[-2] + '.' + output_name.split('.')[-1] # do.x + print(f"Active output: {output_name}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status.sh b/testowe/check_status.sh new file mode 100755 index 0000000..f0aa2ba --- /dev/null +++ b/testowe/check_status.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# Funkcja wyświetlająca pomoc +show_help() { + echo "Użycie: $0 [OPCJE]" + echo + echo "Opcje:" + echo " --show_active_output Wyświetl tylko sterowniki z aktywnymi wyjściami" + echo " --all Wyświetl pełne informacje o sterownikach" + echo " --help Wyświetl tę pomoc" + exit 1 +} + +# Jeśli nie podano żadnych argumentów, wyświetl pomoc +if [ $# -eq 0 ]; then + show_help +fi + +# Domyślne wartości parametrów +show_active_output=false # Domyślnie nie pokazujemy aktywnych wyjść +show_all=false # Domyślnie nie pokazujemy wszystkich informacji + +# Sprawdzenie, jakie parametry zostały podane +for arg in "$@"; do + case $arg in + --show_active_output) + show_active_output=true + shift + ;; + --all) + show_all=true + shift + ;; + --help) + show_help + shift + ;; + *) + echo "Nieznana opcja: $arg" + show_help + ;; + esac +done + +# Plik XML, z którego będziemy pobierać wartości Address +xml_file="ibvunit/ibvunit.xml" + +# Wyciągnięcie wartości Address tylko z sekcji +awk '//' "$xml_file" | grep -oP 'Address="\K\d+' | while read -r address; do + # Uruchomienie polecenia dla każdej wartości Address + output=$(./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.$address.out;);") + + # Jeśli parametr show_all jest ustawiony na 'true', pokaż pełne wyjście polecenia + if [ "$show_all" = true ]; then + echo "Sterownik id.$address:" + echo "$output" + fi + + # Jeśli parametr show_active_output jest ustawiony na 'true', wyświetl tylko sterowniki z włączonymi wyjściami + if [ "$show_active_output" = true ]; then + active_outputs=$(echo "$output" | grep -oP 'do\.\d+ = 1') + + if [ -n "$active_outputs" ]; then + echo "Sterownik id.$address ma aktywne wyjścia:" + echo "$active_outputs" | while read -r line; do + output_name=$(echo "$line" | cut -d' ' -f1) # wyciągnięcie nazwy wyjścia, np. do.0 + echo "Włączone wyjście: $output_name" + done + fi + fi +done + diff --git a/testowe/check_status1.py b/testowe/check_status1.py new file mode 100644 index 0000000..7ca8f94 --- /dev/null +++ b/testowe/check_status1.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Read dok.txt and create a mapping of output names to their descriptions +def load_output_descriptions(dok_file): + descriptions = {} + current_id = None + with open(dok_file, 'r') as file: + for line in file: + line = line.strip() + if line.startswith("id."): # New controller section + current_id = line.split(".")[1] + elif current_id is not None and line.startswith("output.do."): + output_name = f"rs.0.id.{current_id}.{line.split('=')[0].strip()}" + description = line.split('=')[1].strip() + descriptions[output_name] = description + return descriptions + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # Load output descriptions from dok.txt + output_descriptions = load_output_descriptions(dok_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., rs.0.id.39.output.do.2 + output_name = line.split('=')[0].strip() + output_identifier = output_name.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier.split('.')[-1]}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier.split('.')[-1]}" # Corrected to just 'output.do.x' + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + print(f"Controller id.{address} output.{output_identifier.split('.')[-1]} name: {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status2.py b/testowe/check_status2.py new file mode 100644 index 0000000..5556d58 --- /dev/null +++ b/testowe/check_status2.py @@ -0,0 +1,81 @@ +import argparse + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +def parse_arguments(): + parser = argparse.ArgumentParser(description="Controller output monitoring script.") + parser.add_argument('--all', action='store_true', help='Show all controller outputs.') + parser.add_argument('--show-active-output', action='store_true', help='Show only active outputs.') + parser.add_argument('--show-id', type=int, help='Show outputs for a specific controller ID.') + return parser.parse_args() + +def read_dok_file(dok_file): + output_descriptions = {} + controllers = {} + + with open(dok_file, 'r') as f: + lines = f.readlines() + current_id = None + for line in lines: + line = line.strip() + if line.startswith("id."): + current_id = line.split('.')[1] + controllers[current_id] = {'active_outputs': [], 'name': f'Controller {current_id}'} + elif current_id and "=" in line: + key, value = line.split("=") + output_key = key.strip() + output_descriptions[output_key] = value.strip() + # Check if the output key is an active output for the current controller + if output_key.startswith('output.do.'): + controllers[current_id]['active_outputs'].append(output_key) + + return output_descriptions, controllers + +def main(): + args = parse_arguments() + + # Read output descriptions from dok.txt and create controllers dictionary + output_descriptions, controllers = read_dok_file(dok_file) + + if not (args.all or args.show_active_output): + print("Error: You must provide either --all or --show-active-output.") + return + + for address, controller in controllers.items(): + if args.show_id is not None and int(address) != args.show_id: + continue + + if args.all: + print(f"{controller['name']}:") + for output in controller['active_outputs']: + description = output_descriptions.get(output, "Unknown output") + print(f"{output} name: {description}") + + if args.show_active_output: + active_outputs = controller['active_outputs'] + if active_outputs: + for line in active_outputs: + output_identifier = line.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier}" + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + # Change output to include the full output key + print(f"Controller id.{address} output.do.{output_identifier} - {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/desc_gen.py b/testowe/desc_gen.py new file mode 100644 index 0000000..95e1757 --- /dev/null +++ b/testowe/desc_gen.py @@ -0,0 +1,118 @@ +import re + +def load_device_list(file_path): + """Wczytuje listę urządzeń z pliku.""" + with open(file_path, 'r', encoding='utf-8') as file: + lines = [line.strip() for line in file if line.strip()] + return lines + +def parse_devices(lines): + """Grupuje urządzenia według ID, pomijając te, które już mają opis.""" + devices = {} + for line in lines: + if '-' in line: # Pomija urządzenia, które już mają opis + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id not in devices: + devices[device_id] = [] + devices[device_id].append(line) + return devices + +def load_existing_descriptions(file_path): + """Wczytuje istniejące opisy z pliku wynikowego.""" + try: + with open(file_path, 'r', encoding='utf-8') as file: + return {line.split(" - ")[0].strip(): line.strip() for line in file if " - " in line} + except FileNotFoundError: + return {} + +def generate_descriptions(devices, existing_descriptions): + """Interaktywnie generuje opisy dla urządzeń.""" + descriptions = {} + try: + for device_id, components in devices.items(): + print(f"\nID urządzenia: {device_id}") + # Generowanie opisu głównego urządzenia + if f"id {device_id}" in existing_descriptions: + current_desc = existing_descriptions[f"id {device_id}"] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input("Czy chcesz zmodyfikować ten opis? (tak/nie): ").strip().lower() + if modify == "nie": + continue + else: + description = input(f"Podaj nowy opis dla ID {device_id} (np. wiatrołap/kuchnia): ").strip() + if not description: + description = "brak" + descriptions[device_id] = {f"id {device_id}": description} + + # Generowanie opisów dla komponentów urządzenia + for component in components: + if component in existing_descriptions: + current_desc = existing_descriptions[component] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input(f"Czy chcesz zmodyfikować opis dla {component}? (tak/nie): ").strip().lower() + if modify == "nie": + continue + component_desc = input(f"Podaj opis dla {component}: ").strip() + if not component_desc: + component_desc = "brak" + descriptions.setdefault(device_id, {})[component] = component_desc + + except (KeyboardInterrupt, EOFError): # Obsługuje Ctrl+C i Ctrl+Z + print("\nZatrzymano interakcję. Zapisywanie danych...") + return descriptions, True + + return descriptions, False + +def save_descriptions(file_path, descriptions, original_lines, existing_descriptions): + """Zapisuje opisy do pliku, zachowując istniejącą strukturę.""" + with open(file_path, 'w', encoding='utf-8') as file: + for line in original_lines: + if '-' in line: + file.write(line + '\n') + continue + if line in existing_descriptions: + file.write(existing_descriptions[line] + '\n') + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id in descriptions and line in descriptions[device_id]: + file.write(f"{line} - {descriptions[device_id][line]}\n") + else: + file.write(line + '\n') + else: + file.write(line + '\n') + +def main(): + input_file = 'dok.txt' + output_file = 'dok_output.txt' + + print("Wczytywanie urządzeń i istniejących opisów...") + original_lines = load_device_list(input_file) + devices = parse_devices(original_lines) + existing_descriptions = load_existing_descriptions(output_file) + + if not devices: + print("Brak urządzeń do opisania.") + return + + print(f"Znaleziono {len(devices)} urządzeń do opisania.") + + all_descriptions = {} + while devices: + descriptions, should_exit = generate_descriptions(devices, existing_descriptions) + all_descriptions.update(descriptions) + if should_exit: + break + + print("\nZapisywanie opisów do pliku...") + save_descriptions(output_file, all_descriptions, original_lines, existing_descriptions) + print(f"Opisy zapisano w pliku {output_file}.") + print("Zakończono.") + +if __name__ == "__main__": + main() + diff --git a/testowe/dok.txt b/testowe/dok.txt new file mode 100644 index 0000000..8423487 --- /dev/null +++ b/testowe/dok.txt @@ -0,0 +1,239 @@ +id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +id 02 +rs.0.id.02.t.0 +rs.0.id.02.t.1 +rs.0.id.02.t.2 +rs.0.id.02.t.3 +rs.0.id.02.do.t.0 +rs.0.id.02.do.t.1 +rs.0.id.02.do.t.2 +rs.0.id.02.do.t.3 +rs.0.id.02.px0 +rs.0.id.02.px1 + +id 03 +rs.0.id.03.t.0 +rs.0.id.03.t.1 +rs.0.id.03.t.2 +rs.0.id.03.t.3 +rs.0.id.03.do.t.0 +rs.0.id.03.do.t.1 +rs.0.id.03.do.t.2 +rs.0.id.03.do.t.3 +rs.0.id.03.px0 +rs.0.id.03.px1 + +id 04 +rs.0.id.04.t.0 +rs.0.id.04.t.1 +rs.0.id.04.t.2 +rs.0.id.04.t.3 +rs.0.id.04.do.t.0 +rs.0.id.04.do.t.1 +rs.0.id.04.do.t.2 +rs.0.id.04.do.t.3 +rs.0.id.04.px0 +rs.0.id.04.px1 + +id 05 +rs.0.id.05.t.0 +rs.0.id.05.t.1 +rs.0.id.05.t.2 +rs.0.id.05.t.3 +rs.0.id.05.do.t.0 +rs.0.id.05.do.t.1 +rs.0.id.05.do.t.2 +rs.0.id.05.do.t.3 +rs.0.id.05.px0 +rs.0.id.05.px1 + +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oświetlenie H1 +rs.0.id.30.do.t.1 - Oświetlenie H2 +rs.0.id.30.do.t.2 - Oświetlenie K1, szynoprzewód +rs.0.id.30.do.t.3 - Oświetlenie K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak + +id 31 +rs.0.id.31.t.0 +rs.0.id.31.t.1 +rs.0.id.31.t.2 +rs.0.id.31.t.3 +rs.0.id.31.do.t.0 +rs.0.id.31.do.t.1 +rs.0.id.31.do.t.2 +rs.0.id.31.do.t.3 +rs.0.id.31.px0 +rs.0.id.31.px1 + +id 32 +rs.0.id.32.t.0 +rs.0.id.32.t.1 +rs.0.id.32.t.2 +rs.0.id.32.t.3 +rs.0.id.32.do.t.0 +rs.0.id.32.do.t.1 +rs.0.id.32.do.t.2 +rs.0.id.32.do.t.3 +rs.0.id.32.px0 +rs.0.id.32.px1 + +id 33 +rs.0.id.33.t.0 +rs.0.id.33.t.1 +rs.0.id.33.t.2 +rs.0.id.33.t.3 +rs.0.id.33.do.t.0 +rs.0.id.33.do.t.1 +rs.0.id.33.do.t.2 +rs.0.id.33.do.t.3 +rs.0.id.33.px0 +rs.0.id.33.px1 + +id 34 +rs.0.id.34.t.0 +rs.0.id.34.t.1 +rs.0.id.34.t.2 +rs.0.id.34.t.3 +rs.0.id.34.do.t.0 +rs.0.id.34.do.t.1 +rs.0.id.34.do.t.2 +rs.0.id.34.do.t.3 +rs.0.id.34.px0 +rs.0.id.34.px1 + +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 + +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 + +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 + +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 + +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 + +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 + +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 + +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 + +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 + +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/testowe/dok_back.txt b/testowe/dok_back.txt new file mode 100644 index 0000000..8ccd2ec --- /dev/null +++ b/testowe/dok_back.txt @@ -0,0 +1,258 @@ +id.39id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +px.0 = empty +px.1 = empty +output.do.0 = oświetlenie główne +output.do.1 = halogeny nad biurkiem +output.do.2 = chmurka +output.do.3 = kinkiet koło łóżka + +id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +id 02 +rs.0.id.02.t.0 +rs.0.id.02.t.1 +rs.0.id.02.t.2 +rs.0.id.02.t.3 +rs.0.id.02.do.t.0 +rs.0.id.02.do.t.1 +rs.0.id.02.do.t.2 +rs.0.id.02.do.t.3 +rs.0.id.02.px0 +rs.0.id.02.px1 + +id 03 +rs.0.id.03.t.0 +rs.0.id.03.t.1 +rs.0.id.03.t.2 +rs.0.id.03.t.3 +rs.0.id.03.do.t.0 +rs.0.id.03.do.t.1 +rs.0.id.03.do.t.2 +rs.0.id.03.do.t.3 +rs.0.id.03.px0 +rs.0.id.03.px1 + +id 04 +rs.0.id.04.t.0 +rs.0.id.04.t.1 +rs.0.id.04.t.2 +rs.0.id.04.t.3 +rs.0.id.04.do.t.0 +rs.0.id.04.do.t.1 +rs.0.id.04.do.t.2 +rs.0.id.04.do.t.3 +rs.0.id.04.px0 +rs.0.id.04.px1 + +id 05 +rs.0.id.05.t.0 +rs.0.id.05.t.1 +rs.0.id.05.t.2 +rs.0.id.05.t.3 +rs.0.id.05.do.t.0 +rs.0.id.05.do.t.1 +rs.0.id.05.do.t.2 +rs.0.id.05.do.t.3 +rs.0.id.05.px0 +rs.0.id.05.px1 + +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oświetlenie H1 +rs.0.id.30.do.t.1 - Oświetlenie H2 +rs.0.id.30.do.t.2 - Oświetlenie K1, szynoprzewód +rs.0.id.30.do.t.3 - Oświetlenie K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak + +id 31 +rs.0.id.31.t.0 +rs.0.id.31.t.1 +rs.0.id.31.t.2 +rs.0.id.31.t.3 +rs.0.id.31.do.t.0 +rs.0.id.31.do.t.1 +rs.0.id.31.do.t.2 +rs.0.id.31.do.t.3 +rs.0.id.31.px0 +rs.0.id.31.px1 + +id 32 +rs.0.id.32.t.0 +rs.0.id.32.t.1 +rs.0.id.32.t.2 +rs.0.id.32.t.3 +rs.0.id.32.do.t.0 +rs.0.id.32.do.t.1 +rs.0.id.32.do.t.2 +rs.0.id.32.do.t.3 +rs.0.id.32.px0 +rs.0.id.32.px1 + +id 33 +rs.0.id.33.t.0 +rs.0.id.33.t.1 +rs.0.id.33.t.2 +rs.0.id.33.t.3 +rs.0.id.33.do.t.0 +rs.0.id.33.do.t.1 +rs.0.id.33.do.t.2 +rs.0.id.33.do.t.3 +rs.0.id.33.px0 +rs.0.id.33.px1 + +id 34 +rs.0.id.34.t.0 +rs.0.id.34.t.1 +rs.0.id.34.t.2 +rs.0.id.34.t.3 +rs.0.id.34.do.t.0 +rs.0.id.34.do.t.1 +rs.0.id.34.do.t.2 +rs.0.id.34.do.t.3 +rs.0.id.34.px0 +rs.0.id.34.px1 + +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 + +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 + +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 + +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 + +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 + +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 + +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 + +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 + +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 + +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/testowe/dok_output.txt b/testowe/dok_output.txt new file mode 100644 index 0000000..6c98aa8 --- /dev/null +++ b/testowe/dok_output.txt @@ -0,0 +1,220 @@ +id 01 +rs.0.id.01.t.0 - czujnik temperatury wymiennika na kominku +rs.0.id.01.t.1 - brak +rs.0.id.01.t.2 - brak +rs.0.id.01.t.3 - brak +rs.0.id.01.do.t.0 - pompa kominka +rs.0.id.01.do.t.1 - brak +rs.0.id.01.do.t.2 - brak +rs.0.id.01.do.t.3 - brak +rs.0.id.01.px0 - brak +rs.0.id.01.px1 - brak +id 02 +rs.0.id.02.t.0 - brak +rs.0.id.02.t.1 - brak +rs.0.id.02.t.2 - brak +rs.0.id.02.t.3 - brak +rs.0.id.02.do.t.0 - brak +rs.0.id.02.do.t.1 - brak +rs.0.id.02.do.t.2 - brak +rs.0.id.02.do.t.3 - brak +rs.0.id.02.px0 - brak +rs.0.id.02.px1 - brak +id 03 +rs.0.id.03.t.0 - brak +rs.0.id.03.t.1 - brak +rs.0.id.03.t.2 - brak +rs.0.id.03.t.3 - brak +rs.0.id.03.do.t.0 - brak +rs.0.id.03.do.t.1 - brak +rs.0.id.03.do.t.2 - brak +rs.0.id.03.do.t.3 - brak +rs.0.id.03.px0 - brak +rs.0.id.03.px1 - brak +id 04 +rs.0.id.04.t.0 - brak +rs.0.id.04.t.1 - brak +rs.0.id.04.t.2 - brak +rs.0.id.04.t.3 - brak +rs.0.id.04.do.t.0 - brak +rs.0.id.04.do.t.1 - brak +rs.0.id.04.do.t.2 - brak +rs.0.id.04.do.t.3 - brak +rs.0.id.04.px0 - brak +rs.0.id.04.px1 - brak +id 05 +rs.0.id.05.t.0 - brak +rs.0.id.05.t.1 - brak +rs.0.id.05.t.2 - brak +rs.0.id.05.t.3 - brak +rs.0.id.05.do.t.0 - brak +rs.0.id.05.do.t.1 - brak +rs.0.id.05.do.t.2 - brak +rs.0.id.05.do.t.3 - brak +rs.0.id.05.px0 - brak +rs.0.id.05.px1 - brak +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oś H1 +rs.0.id.30.do.t.1 - Oś H2 +rs.0.id.30.do.t.2 - Oś K1, szynoprzewód +rs.0.id.30.do.t.3 - Oś K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak +id 31 +rs.0.id.31.t.0 - przycisk K3, zug 5 +rs.0.id.31.t.1 - przycisk K4, zug 7 +rs.0.id.31.t.2 - przycisk K5 +rs.0.id.31.t.3 - przycisk K6 +rs.0.id.31.do.t.0 - Oś K3, halogeny okno +rs.0.id.31.do.t.1 - Oś K4, lampy nad barem +rs.0.id.31.do.t.2 - Oś K5, ledy pod półkami +rs.0.id.31.do.t.3 - Os K6, led okno +rs.0.id.31.px0 - brak +rs.0.id.31.px1 - brak +id 32 +rs.0.id.32.t.0 - przycisk J1, zug 14, J1 czarny +rs.0.id.32.t.1 - przycisk J2, zug 14,J2 brazowy +rs.0.id.32.t.2 - przycisk S1, zug 10, S1 czarny +rs.0.id.32.t.3 - przycisk S5, zug 10, S5 brazowy +rs.0.id.32.do.t.0 - Oś J1, Nad stołem +rs.0.id.32.do.t.1 - Oś J2, Nad stołem # połączone razem J1 i J2 +rs.0.id.32.do.t.2 - Oś S1, Ring salon +rs.0.id.32.do.t.3 - oś S5, led dekoracyjny koło kanapy +rs.0.id.32.px0 - brak +rs.0.id.32.px1 - brak +id 33 +rs.0.id.33.t.0 - przycisk S2, zug 11 +rs.0.id.33.t.1 - przycisk S3, zug 11 +rs.0.id.33.t.2 - przycisk S4 +rs.0.id.33.t.3 - przycisk S6 +rs.0.id.33.do.t.0 - Oś S2, spotlight za kanapom +rs.0.id.33.do.t.1 - Oś S3, spotlight przed TV +rs.0.id.33.do.t.2 - Oś S4, Led TV +rs.0.id.33.do.t.3 - Oś S6, Led sufit wnęka, przewód 4.4, zug 13 +rs.0.id.33.px0 - brak +rs.0.id.33.px1 - brak +id 34 +rs.0.id.34.t.0 - przycisk H3, zug 16, szyno przewód +rs.0.id.34.t.1 - przycisk H4, zug 16, szyno przewód +rs.0.id.34.t.2 - przycisk H5 +rs.0.id.34.t.3 - przycisk H6 +rs.0.id.34.do.t.0 - Oś H3, szyno przewód +rs.0.id.34.do.t.1 - Oś H4, szyno przewód +rs.0.id.34.do.t.2 - Oś H5, zug 17, przedów 5.2 Ledy pionowe +rs.0.id.34.do.t.3 - Oś H6, zug 18, przewód 5.3 Led kominek #Brazowy 230v gniazdo kominek, niebieski N, Żółty 230V zasilacz Led kominek +rs.0.id.34.px0 - brak +rs.0.id.34.px1 - brak +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/testowe/test1.sh b/testowe/test1.sh new file mode 100755 index 0000000..570a98a --- /dev/null +++ b/testowe/test1.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Funkcja dodająca komendy do crontaba +disable_light_cronjob() { + (crontab -l 2>/dev/null; echo "25 2 * * * /ibsystem/ibls -a 127.0.0.1 --pretty -p 2001 -c 'set(rs.0.id.35.setting.light.1=1;);'") | crontab - + (crontab -l 2>/dev/null; echo "26 2 * * * /ibsystem/ibls -a 127.0.0.1 --pretty -p 2001 -c 'set(rs.0.id.35.setting.light.1=0;);'") | crontab - +} + +# Wywołanie funkcji +disable_light_cronjob + diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/proj-ib-lighting-rs485-zarki.yaml b/proj-ib-lighting-rs485-zarki.yaml index 3a47859..214118d 100644 --- a/proj-ib-lighting-rs485-zarki.yaml +++ b/proj-ib-lighting-rs485-zarki.yaml @@ -278,7 +278,7 @@ - io_id: "input.t.1" status: "ok" mapping: "" - description: """ + description: "" - io_id: "input.t.2" status: "ok" mapping: "" diff --git a/testowe/check_perm.sh b/testowe/check_perm.sh new file mode 100755 index 0000000..a9f141e --- /dev/null +++ b/testowe/check_perm.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +chown -R root:root /ibsystem +chmod 755 /ibsystem/*.sh +chmod 755 /ibsystem/ibvunit/ibvunit +chmod 755 /ibsystem/ibmanager/ibmanager +chmod 755 /ibsystem/ibls diff --git a/testowe/check_status.py b/testowe/check_status.py new file mode 100644 index 0000000..6457cef --- /dev/null +++ b/testowe/check_status.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., do.x + output_name = line.split('=')[0].strip() + output_name = output_name.split('.')[-2] + '.' + output_name.split('.')[-1] # do.x + print(f"Active output: {output_name}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status.sh b/testowe/check_status.sh new file mode 100755 index 0000000..f0aa2ba --- /dev/null +++ b/testowe/check_status.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# Funkcja wyświetlająca pomoc +show_help() { + echo "Użycie: $0 [OPCJE]" + echo + echo "Opcje:" + echo " --show_active_output Wyświetl tylko sterowniki z aktywnymi wyjściami" + echo " --all Wyświetl pełne informacje o sterownikach" + echo " --help Wyświetl tę pomoc" + exit 1 +} + +# Jeśli nie podano żadnych argumentów, wyświetl pomoc +if [ $# -eq 0 ]; then + show_help +fi + +# Domyślne wartości parametrów +show_active_output=false # Domyślnie nie pokazujemy aktywnych wyjść +show_all=false # Domyślnie nie pokazujemy wszystkich informacji + +# Sprawdzenie, jakie parametry zostały podane +for arg in "$@"; do + case $arg in + --show_active_output) + show_active_output=true + shift + ;; + --all) + show_all=true + shift + ;; + --help) + show_help + shift + ;; + *) + echo "Nieznana opcja: $arg" + show_help + ;; + esac +done + +# Plik XML, z którego będziemy pobierać wartości Address +xml_file="ibvunit/ibvunit.xml" + +# Wyciągnięcie wartości Address tylko z sekcji +awk '//' "$xml_file" | grep -oP 'Address="\K\d+' | while read -r address; do + # Uruchomienie polecenia dla każdej wartości Address + output=$(./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.$address.out;);") + + # Jeśli parametr show_all jest ustawiony na 'true', pokaż pełne wyjście polecenia + if [ "$show_all" = true ]; then + echo "Sterownik id.$address:" + echo "$output" + fi + + # Jeśli parametr show_active_output jest ustawiony na 'true', wyświetl tylko sterowniki z włączonymi wyjściami + if [ "$show_active_output" = true ]; then + active_outputs=$(echo "$output" | grep -oP 'do\.\d+ = 1') + + if [ -n "$active_outputs" ]; then + echo "Sterownik id.$address ma aktywne wyjścia:" + echo "$active_outputs" | while read -r line; do + output_name=$(echo "$line" | cut -d' ' -f1) # wyciągnięcie nazwy wyjścia, np. do.0 + echo "Włączone wyjście: $output_name" + done + fi + fi +done + diff --git a/testowe/check_status1.py b/testowe/check_status1.py new file mode 100644 index 0000000..7ca8f94 --- /dev/null +++ b/testowe/check_status1.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Read dok.txt and create a mapping of output names to their descriptions +def load_output_descriptions(dok_file): + descriptions = {} + current_id = None + with open(dok_file, 'r') as file: + for line in file: + line = line.strip() + if line.startswith("id."): # New controller section + current_id = line.split(".")[1] + elif current_id is not None and line.startswith("output.do."): + output_name = f"rs.0.id.{current_id}.{line.split('=')[0].strip()}" + description = line.split('=')[1].strip() + descriptions[output_name] = description + return descriptions + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # Load output descriptions from dok.txt + output_descriptions = load_output_descriptions(dok_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., rs.0.id.39.output.do.2 + output_name = line.split('=')[0].strip() + output_identifier = output_name.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier.split('.')[-1]}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier.split('.')[-1]}" # Corrected to just 'output.do.x' + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + print(f"Controller id.{address} output.{output_identifier.split('.')[-1]} name: {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status2.py b/testowe/check_status2.py new file mode 100644 index 0000000..5556d58 --- /dev/null +++ b/testowe/check_status2.py @@ -0,0 +1,81 @@ +import argparse + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +def parse_arguments(): + parser = argparse.ArgumentParser(description="Controller output monitoring script.") + parser.add_argument('--all', action='store_true', help='Show all controller outputs.') + parser.add_argument('--show-active-output', action='store_true', help='Show only active outputs.') + parser.add_argument('--show-id', type=int, help='Show outputs for a specific controller ID.') + return parser.parse_args() + +def read_dok_file(dok_file): + output_descriptions = {} + controllers = {} + + with open(dok_file, 'r') as f: + lines = f.readlines() + current_id = None + for line in lines: + line = line.strip() + if line.startswith("id."): + current_id = line.split('.')[1] + controllers[current_id] = {'active_outputs': [], 'name': f'Controller {current_id}'} + elif current_id and "=" in line: + key, value = line.split("=") + output_key = key.strip() + output_descriptions[output_key] = value.strip() + # Check if the output key is an active output for the current controller + if output_key.startswith('output.do.'): + controllers[current_id]['active_outputs'].append(output_key) + + return output_descriptions, controllers + +def main(): + args = parse_arguments() + + # Read output descriptions from dok.txt and create controllers dictionary + output_descriptions, controllers = read_dok_file(dok_file) + + if not (args.all or args.show_active_output): + print("Error: You must provide either --all or --show-active-output.") + return + + for address, controller in controllers.items(): + if args.show_id is not None and int(address) != args.show_id: + continue + + if args.all: + print(f"{controller['name']}:") + for output in controller['active_outputs']: + description = output_descriptions.get(output, "Unknown output") + print(f"{output} name: {description}") + + if args.show_active_output: + active_outputs = controller['active_outputs'] + if active_outputs: + for line in active_outputs: + output_identifier = line.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier}" + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + # Change output to include the full output key + print(f"Controller id.{address} output.do.{output_identifier} - {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/desc_gen.py b/testowe/desc_gen.py new file mode 100644 index 0000000..95e1757 --- /dev/null +++ b/testowe/desc_gen.py @@ -0,0 +1,118 @@ +import re + +def load_device_list(file_path): + """Wczytuje listę urządzeń z pliku.""" + with open(file_path, 'r', encoding='utf-8') as file: + lines = [line.strip() for line in file if line.strip()] + return lines + +def parse_devices(lines): + """Grupuje urządzenia według ID, pomijając te, które już mają opis.""" + devices = {} + for line in lines: + if '-' in line: # Pomija urządzenia, które już mają opis + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id not in devices: + devices[device_id] = [] + devices[device_id].append(line) + return devices + +def load_existing_descriptions(file_path): + """Wczytuje istniejące opisy z pliku wynikowego.""" + try: + with open(file_path, 'r', encoding='utf-8') as file: + return {line.split(" - ")[0].strip(): line.strip() for line in file if " - " in line} + except FileNotFoundError: + return {} + +def generate_descriptions(devices, existing_descriptions): + """Interaktywnie generuje opisy dla urządzeń.""" + descriptions = {} + try: + for device_id, components in devices.items(): + print(f"\nID urządzenia: {device_id}") + # Generowanie opisu głównego urządzenia + if f"id {device_id}" in existing_descriptions: + current_desc = existing_descriptions[f"id {device_id}"] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input("Czy chcesz zmodyfikować ten opis? (tak/nie): ").strip().lower() + if modify == "nie": + continue + else: + description = input(f"Podaj nowy opis dla ID {device_id} (np. wiatrołap/kuchnia): ").strip() + if not description: + description = "brak" + descriptions[device_id] = {f"id {device_id}": description} + + # Generowanie opisów dla komponentów urządzenia + for component in components: + if component in existing_descriptions: + current_desc = existing_descriptions[component] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input(f"Czy chcesz zmodyfikować opis dla {component}? (tak/nie): ").strip().lower() + if modify == "nie": + continue + component_desc = input(f"Podaj opis dla {component}: ").strip() + if not component_desc: + component_desc = "brak" + descriptions.setdefault(device_id, {})[component] = component_desc + + except (KeyboardInterrupt, EOFError): # Obsługuje Ctrl+C i Ctrl+Z + print("\nZatrzymano interakcję. Zapisywanie danych...") + return descriptions, True + + return descriptions, False + +def save_descriptions(file_path, descriptions, original_lines, existing_descriptions): + """Zapisuje opisy do pliku, zachowując istniejącą strukturę.""" + with open(file_path, 'w', encoding='utf-8') as file: + for line in original_lines: + if '-' in line: + file.write(line + '\n') + continue + if line in existing_descriptions: + file.write(existing_descriptions[line] + '\n') + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id in descriptions and line in descriptions[device_id]: + file.write(f"{line} - {descriptions[device_id][line]}\n") + else: + file.write(line + '\n') + else: + file.write(line + '\n') + +def main(): + input_file = 'dok.txt' + output_file = 'dok_output.txt' + + print("Wczytywanie urządzeń i istniejących opisów...") + original_lines = load_device_list(input_file) + devices = parse_devices(original_lines) + existing_descriptions = load_existing_descriptions(output_file) + + if not devices: + print("Brak urządzeń do opisania.") + return + + print(f"Znaleziono {len(devices)} urządzeń do opisania.") + + all_descriptions = {} + while devices: + descriptions, should_exit = generate_descriptions(devices, existing_descriptions) + all_descriptions.update(descriptions) + if should_exit: + break + + print("\nZapisywanie opisów do pliku...") + save_descriptions(output_file, all_descriptions, original_lines, existing_descriptions) + print(f"Opisy zapisano w pliku {output_file}.") + print("Zakończono.") + +if __name__ == "__main__": + main() + diff --git a/testowe/dok.txt b/testowe/dok.txt new file mode 100644 index 0000000..8423487 --- /dev/null +++ b/testowe/dok.txt @@ -0,0 +1,239 @@ +id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +id 02 +rs.0.id.02.t.0 +rs.0.id.02.t.1 +rs.0.id.02.t.2 +rs.0.id.02.t.3 +rs.0.id.02.do.t.0 +rs.0.id.02.do.t.1 +rs.0.id.02.do.t.2 +rs.0.id.02.do.t.3 +rs.0.id.02.px0 +rs.0.id.02.px1 + +id 03 +rs.0.id.03.t.0 +rs.0.id.03.t.1 +rs.0.id.03.t.2 +rs.0.id.03.t.3 +rs.0.id.03.do.t.0 +rs.0.id.03.do.t.1 +rs.0.id.03.do.t.2 +rs.0.id.03.do.t.3 +rs.0.id.03.px0 +rs.0.id.03.px1 + +id 04 +rs.0.id.04.t.0 +rs.0.id.04.t.1 +rs.0.id.04.t.2 +rs.0.id.04.t.3 +rs.0.id.04.do.t.0 +rs.0.id.04.do.t.1 +rs.0.id.04.do.t.2 +rs.0.id.04.do.t.3 +rs.0.id.04.px0 +rs.0.id.04.px1 + +id 05 +rs.0.id.05.t.0 +rs.0.id.05.t.1 +rs.0.id.05.t.2 +rs.0.id.05.t.3 +rs.0.id.05.do.t.0 +rs.0.id.05.do.t.1 +rs.0.id.05.do.t.2 +rs.0.id.05.do.t.3 +rs.0.id.05.px0 +rs.0.id.05.px1 + +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oświetlenie H1 +rs.0.id.30.do.t.1 - Oświetlenie H2 +rs.0.id.30.do.t.2 - Oświetlenie K1, szynoprzewód +rs.0.id.30.do.t.3 - Oświetlenie K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak + +id 31 +rs.0.id.31.t.0 +rs.0.id.31.t.1 +rs.0.id.31.t.2 +rs.0.id.31.t.3 +rs.0.id.31.do.t.0 +rs.0.id.31.do.t.1 +rs.0.id.31.do.t.2 +rs.0.id.31.do.t.3 +rs.0.id.31.px0 +rs.0.id.31.px1 + +id 32 +rs.0.id.32.t.0 +rs.0.id.32.t.1 +rs.0.id.32.t.2 +rs.0.id.32.t.3 +rs.0.id.32.do.t.0 +rs.0.id.32.do.t.1 +rs.0.id.32.do.t.2 +rs.0.id.32.do.t.3 +rs.0.id.32.px0 +rs.0.id.32.px1 + +id 33 +rs.0.id.33.t.0 +rs.0.id.33.t.1 +rs.0.id.33.t.2 +rs.0.id.33.t.3 +rs.0.id.33.do.t.0 +rs.0.id.33.do.t.1 +rs.0.id.33.do.t.2 +rs.0.id.33.do.t.3 +rs.0.id.33.px0 +rs.0.id.33.px1 + +id 34 +rs.0.id.34.t.0 +rs.0.id.34.t.1 +rs.0.id.34.t.2 +rs.0.id.34.t.3 +rs.0.id.34.do.t.0 +rs.0.id.34.do.t.1 +rs.0.id.34.do.t.2 +rs.0.id.34.do.t.3 +rs.0.id.34.px0 +rs.0.id.34.px1 + +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 + +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 + +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 + +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 + +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 + +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 + +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 + +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 + +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 + +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/testowe/dok_back.txt b/testowe/dok_back.txt new file mode 100644 index 0000000..8ccd2ec --- /dev/null +++ b/testowe/dok_back.txt @@ -0,0 +1,258 @@ +id.39id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +px.0 = empty +px.1 = empty +output.do.0 = oświetlenie główne +output.do.1 = halogeny nad biurkiem +output.do.2 = chmurka +output.do.3 = kinkiet koło łóżka + +id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +id 02 +rs.0.id.02.t.0 +rs.0.id.02.t.1 +rs.0.id.02.t.2 +rs.0.id.02.t.3 +rs.0.id.02.do.t.0 +rs.0.id.02.do.t.1 +rs.0.id.02.do.t.2 +rs.0.id.02.do.t.3 +rs.0.id.02.px0 +rs.0.id.02.px1 + +id 03 +rs.0.id.03.t.0 +rs.0.id.03.t.1 +rs.0.id.03.t.2 +rs.0.id.03.t.3 +rs.0.id.03.do.t.0 +rs.0.id.03.do.t.1 +rs.0.id.03.do.t.2 +rs.0.id.03.do.t.3 +rs.0.id.03.px0 +rs.0.id.03.px1 + +id 04 +rs.0.id.04.t.0 +rs.0.id.04.t.1 +rs.0.id.04.t.2 +rs.0.id.04.t.3 +rs.0.id.04.do.t.0 +rs.0.id.04.do.t.1 +rs.0.id.04.do.t.2 +rs.0.id.04.do.t.3 +rs.0.id.04.px0 +rs.0.id.04.px1 + +id 05 +rs.0.id.05.t.0 +rs.0.id.05.t.1 +rs.0.id.05.t.2 +rs.0.id.05.t.3 +rs.0.id.05.do.t.0 +rs.0.id.05.do.t.1 +rs.0.id.05.do.t.2 +rs.0.id.05.do.t.3 +rs.0.id.05.px0 +rs.0.id.05.px1 + +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oświetlenie H1 +rs.0.id.30.do.t.1 - Oświetlenie H2 +rs.0.id.30.do.t.2 - Oświetlenie K1, szynoprzewód +rs.0.id.30.do.t.3 - Oświetlenie K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak + +id 31 +rs.0.id.31.t.0 +rs.0.id.31.t.1 +rs.0.id.31.t.2 +rs.0.id.31.t.3 +rs.0.id.31.do.t.0 +rs.0.id.31.do.t.1 +rs.0.id.31.do.t.2 +rs.0.id.31.do.t.3 +rs.0.id.31.px0 +rs.0.id.31.px1 + +id 32 +rs.0.id.32.t.0 +rs.0.id.32.t.1 +rs.0.id.32.t.2 +rs.0.id.32.t.3 +rs.0.id.32.do.t.0 +rs.0.id.32.do.t.1 +rs.0.id.32.do.t.2 +rs.0.id.32.do.t.3 +rs.0.id.32.px0 +rs.0.id.32.px1 + +id 33 +rs.0.id.33.t.0 +rs.0.id.33.t.1 +rs.0.id.33.t.2 +rs.0.id.33.t.3 +rs.0.id.33.do.t.0 +rs.0.id.33.do.t.1 +rs.0.id.33.do.t.2 +rs.0.id.33.do.t.3 +rs.0.id.33.px0 +rs.0.id.33.px1 + +id 34 +rs.0.id.34.t.0 +rs.0.id.34.t.1 +rs.0.id.34.t.2 +rs.0.id.34.t.3 +rs.0.id.34.do.t.0 +rs.0.id.34.do.t.1 +rs.0.id.34.do.t.2 +rs.0.id.34.do.t.3 +rs.0.id.34.px0 +rs.0.id.34.px1 + +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 + +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 + +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 + +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 + +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 + +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 + +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 + +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 + +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 + +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/testowe/dok_output.txt b/testowe/dok_output.txt new file mode 100644 index 0000000..6c98aa8 --- /dev/null +++ b/testowe/dok_output.txt @@ -0,0 +1,220 @@ +id 01 +rs.0.id.01.t.0 - czujnik temperatury wymiennika na kominku +rs.0.id.01.t.1 - brak +rs.0.id.01.t.2 - brak +rs.0.id.01.t.3 - brak +rs.0.id.01.do.t.0 - pompa kominka +rs.0.id.01.do.t.1 - brak +rs.0.id.01.do.t.2 - brak +rs.0.id.01.do.t.3 - brak +rs.0.id.01.px0 - brak +rs.0.id.01.px1 - brak +id 02 +rs.0.id.02.t.0 - brak +rs.0.id.02.t.1 - brak +rs.0.id.02.t.2 - brak +rs.0.id.02.t.3 - brak +rs.0.id.02.do.t.0 - brak +rs.0.id.02.do.t.1 - brak +rs.0.id.02.do.t.2 - brak +rs.0.id.02.do.t.3 - brak +rs.0.id.02.px0 - brak +rs.0.id.02.px1 - brak +id 03 +rs.0.id.03.t.0 - brak +rs.0.id.03.t.1 - brak +rs.0.id.03.t.2 - brak +rs.0.id.03.t.3 - brak +rs.0.id.03.do.t.0 - brak +rs.0.id.03.do.t.1 - brak +rs.0.id.03.do.t.2 - brak +rs.0.id.03.do.t.3 - brak +rs.0.id.03.px0 - brak +rs.0.id.03.px1 - brak +id 04 +rs.0.id.04.t.0 - brak +rs.0.id.04.t.1 - brak +rs.0.id.04.t.2 - brak +rs.0.id.04.t.3 - brak +rs.0.id.04.do.t.0 - brak +rs.0.id.04.do.t.1 - brak +rs.0.id.04.do.t.2 - brak +rs.0.id.04.do.t.3 - brak +rs.0.id.04.px0 - brak +rs.0.id.04.px1 - brak +id 05 +rs.0.id.05.t.0 - brak +rs.0.id.05.t.1 - brak +rs.0.id.05.t.2 - brak +rs.0.id.05.t.3 - brak +rs.0.id.05.do.t.0 - brak +rs.0.id.05.do.t.1 - brak +rs.0.id.05.do.t.2 - brak +rs.0.id.05.do.t.3 - brak +rs.0.id.05.px0 - brak +rs.0.id.05.px1 - brak +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oś H1 +rs.0.id.30.do.t.1 - Oś H2 +rs.0.id.30.do.t.2 - Oś K1, szynoprzewód +rs.0.id.30.do.t.3 - Oś K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak +id 31 +rs.0.id.31.t.0 - przycisk K3, zug 5 +rs.0.id.31.t.1 - przycisk K4, zug 7 +rs.0.id.31.t.2 - przycisk K5 +rs.0.id.31.t.3 - przycisk K6 +rs.0.id.31.do.t.0 - Oś K3, halogeny okno +rs.0.id.31.do.t.1 - Oś K4, lampy nad barem +rs.0.id.31.do.t.2 - Oś K5, ledy pod półkami +rs.0.id.31.do.t.3 - Os K6, led okno +rs.0.id.31.px0 - brak +rs.0.id.31.px1 - brak +id 32 +rs.0.id.32.t.0 - przycisk J1, zug 14, J1 czarny +rs.0.id.32.t.1 - przycisk J2, zug 14,J2 brazowy +rs.0.id.32.t.2 - przycisk S1, zug 10, S1 czarny +rs.0.id.32.t.3 - przycisk S5, zug 10, S5 brazowy +rs.0.id.32.do.t.0 - Oś J1, Nad stołem +rs.0.id.32.do.t.1 - Oś J2, Nad stołem # połączone razem J1 i J2 +rs.0.id.32.do.t.2 - Oś S1, Ring salon +rs.0.id.32.do.t.3 - oś S5, led dekoracyjny koło kanapy +rs.0.id.32.px0 - brak +rs.0.id.32.px1 - brak +id 33 +rs.0.id.33.t.0 - przycisk S2, zug 11 +rs.0.id.33.t.1 - przycisk S3, zug 11 +rs.0.id.33.t.2 - przycisk S4 +rs.0.id.33.t.3 - przycisk S6 +rs.0.id.33.do.t.0 - Oś S2, spotlight za kanapom +rs.0.id.33.do.t.1 - Oś S3, spotlight przed TV +rs.0.id.33.do.t.2 - Oś S4, Led TV +rs.0.id.33.do.t.3 - Oś S6, Led sufit wnęka, przewód 4.4, zug 13 +rs.0.id.33.px0 - brak +rs.0.id.33.px1 - brak +id 34 +rs.0.id.34.t.0 - przycisk H3, zug 16, szyno przewód +rs.0.id.34.t.1 - przycisk H4, zug 16, szyno przewód +rs.0.id.34.t.2 - przycisk H5 +rs.0.id.34.t.3 - przycisk H6 +rs.0.id.34.do.t.0 - Oś H3, szyno przewód +rs.0.id.34.do.t.1 - Oś H4, szyno przewód +rs.0.id.34.do.t.2 - Oś H5, zug 17, przedów 5.2 Ledy pionowe +rs.0.id.34.do.t.3 - Oś H6, zug 18, przewód 5.3 Led kominek #Brazowy 230v gniazdo kominek, niebieski N, Żółty 230V zasilacz Led kominek +rs.0.id.34.px0 - brak +rs.0.id.34.px1 - brak +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/testowe/test1.sh b/testowe/test1.sh new file mode 100755 index 0000000..570a98a --- /dev/null +++ b/testowe/test1.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Funkcja dodająca komendy do crontaba +disable_light_cronjob() { + (crontab -l 2>/dev/null; echo "25 2 * * * /ibsystem/ibls -a 127.0.0.1 --pretty -p 2001 -c 'set(rs.0.id.35.setting.light.1=1;);'") | crontab - + (crontab -l 2>/dev/null; echo "26 2 * * * /ibsystem/ibls -a 127.0.0.1 --pretty -p 2001 -c 'set(rs.0.id.35.setting.light.1=0;);'") | crontab - +} + +# Wywołanie funkcji +disable_light_cronjob + diff --git a/wydruk_id2-5.html b/wydruk_id2-5.html new file mode 100644 index 0000000..40fe037 --- /dev/null +++ b/wydruk_id2-5.html @@ -0,0 +1,223 @@ + + + +Sterowniki ID2-ID5 + + +

STEROWNIKI ID2-ID5 - DO EDYCJI (wydrukuj i uzupełnij)

+
===========================================
+ STEROWNIKI ID2-ID5 - DO EDYCJI
+ Data wydruku: $(date)
+===========================================
+
+      - device_id: "rs.0.id.2"
+        model_id: "IB-CTRL-IO-RS485"
+        location: "ID2 Sterownik ogrzewania podłogowego"
+        description: |
+          Sterownik ID2 Sterownik ogrzewania podłogowego.
+        connections:
+          - bus_id: "rs.0"
+            address: "id.2"
+        io:
+          - io_id: "input.t.0"
+            status: "ok"
+            mapping: ""
+            description: "XXX"
+          - io_id: "input.t.1"
+            status: "ok"
+            mapping: ""
+            description: "XXX"
+          - io_id: "input.t.2"
+            status: "ok"
+            mapping: ""
+            description: "XXX"
+          - io_id: "input.t.3"
+            status: "ok"
+            mapping: ""
+            description: "XXX"
+          - io_id: "output.do.0"
+            status: "ok"
+            mapping: ""
+            description: "zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu)"
+          - io_id: "output.do.1"
+            status: "ok"
+            mapping: ""
+            description: "zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor]"
+          - io_id: "output.do.2"
+            status: "ok"
+            mapping: ""
+            description: "zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu)"
+          - io_id: "output.do.3"
+            status: "ok"
+            mapping: ""
+            description: "zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor]"
+          - io_id: "output.px.0"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0"
+          - io_id: "output.px.1"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX."
+        extension_modules: []
+      # Strefa 3: starownik ID3 przenieść czujniki z ID5
+      - device_id: "rs.0.id.3"
+        model_id: "IB-CTRL-IO-RS485"
+        location: "ID3"
+        description: |
+          Sterownik ID3 syterownik ogrzewania podłogowego.
+        connections:
+          - bus_id: "rs.0"
+            address: "id.3"
+        io:
+          - io_id: "input.t.0"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Basia" #do przeniesienia z ID5
+          - io_id: "input.t.1"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Ania" #do przeniesienia z ID5
+          - io_id: "input.t.2"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. WC" #do przeniesienia z ID5
+          - io_id: "input.t.3"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Wiatrołap" #do przeniesienia z ID5
+          - io_id: "output.do.0"
+            status: "ok"
+            mapping: ""
+            description: "siłownik rozdzielacz R1 - Basia"
+          - io_id: "output.do.1"
+            status: "ok"
+            mapping: ""
+            description: "siłownik rozdzielacz R1 - Ania"
+          - io_id: "output.do.2"
+            status: "ok"
+            mapping: ""
+            description: "siłownik pokoju - WC"
+          - io_id: "output.do.3"
+            status: "ok"
+            mapping: ""
+            description: "siłownik pokoju - Wiatrołap"
+          - io_id: "output.px.0"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0"
+          - io_id: "output.px.1"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX."
+        extension_modules: []
+
+      # Strefa 4: starownik ID4 do przeniesienie sterowanie nawadnianiem do ID6
+      - device_id: "rs.0.id.4"
+        model_id: "IB-CTRL-IO-RS485"
+        location: "ID4"
+        description: |
+          Sterownik ID4 ogrzewania podłogowego.
+        connections:
+          - bus_id: "rs.0"
+            address: "id.4"
+        io:
+          - io_id: "input.t.0"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Salon"
+          - io_id: "input.t.1"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Biuro Wojtek"
+          - io_id: "input.t.2"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Sypialnia"
+          - io_id: "input.t.3"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Duża łazienka"
+          - io_id: "output.do.0"
+            status: "ok"
+            mapping: ""
+            description: "siłownik rozdzielacz R2 - salon" #obecnie jest "pompa głębinowa"
+          - io_id: "output.do.1"
+            status: "ok"
+            mapping: ""
+            description: "siłownik rozdzielacz R2 - biuro Wojtek" #obecnie jest "elektro zawór zraszaczy sekcja X`"
+          - io_id: "output.do.2"
+            status: "ok"
+            mapping: ""
+            description: "siłownik rozdzielacz R2 - sypialnia" # obecnie jest "elektro zawór zraszaczy sekcja X"
+          - io_id: "output.do.3"
+            status: "ok"
+            mapping: ""
+            description: "siłownik rozdzielacz R2 - duża łazienka" # obecnie jest "elektro zawór zraszaczy sekcja X"
+          - io_id: "output.px.0"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0"
+          - io_id: "output.px.1"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX."
+        extension_modules: []
+      # Strefa 5: starownik ID5
+      - device_id: "rs.0.id.5"
+        model_id: "IB-CTRL-IO-RS485"
+        location: "ID5"
+        description: |
+          Sterownik ID5 do sterowania nawadnianiem.
+        connections:
+          - bus_id: "rs.0"
+            address: "id.5"
+        io:
+          - io_id: "input.t.0"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Basia" #do przeniesienia do ID3
+          - io_id: "input.t.1"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Biuro Ania" #do przeniesienia do ID3
+          - io_id: "input.t.2"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. WC" #do przeniesienia do ID3
+          - io_id: "input.t.3"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Wiatrołap" #do przeniesienia do ID3
+          - io_id: "output.do.0"
+            status: "ok"
+            mapping: ""
+            description: "elektro zawór zraszaczy sekcja X"
+          - io_id: "output.do.1"
+            status: "ok"
+            mapping: ""
+            description: "elektro zawór zraszaczy sekcja X"
+          - io_id: "output.do.2"
+            status: "ok"
+            mapping: ""
+            description: "elektro zawór zraszaczy sekcja X"
+          - io_id: "output.do.3"
+            status: "ok"
+            mapping: ""
+            description: "elektro zawór zraszaczy sekcja X"
+          - io_id: "output.px.0"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX. Adres rs.0.id.5.px0"
+          - io_id: "output.px.1"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX."
+        extension_modules: []
+      # Strefa 6: starownik ID6 przenieść tu wszystko z ID4 - sterowanie nawadnianiem -- dołożyć sterownik
+      - device_id: "rs.0.id.6"
+
\ No newline at end of file diff --git a/dokumentacja.md b/dokumentacja.md new file mode 100644 index 0000000..24b1548 --- /dev/null +++ b/dokumentacja.md @@ -0,0 +1,417 @@ +# Projekt + +**Opis:** Implementacja systemu sterowania oświetleniem w poszczególnych strefach (pomieszczeniach) za pomocą modułów I/O RS485. +System opiera się na cyfrowych wejściach (przyciski) i cyfrowych wyjściach (oświetlenie ON/OFF) oraz opcjonalnie wyjściach PX (PWM/ściemnianie). +Każda strefa (ID 30-41) obsługiwana jest przez dedykowany moduł I/O. + + +## Statystyki + +- **Liczba urządzeń:** 17 +- **Łączna liczba I/O:** 170 + +## Lista urządzeń + +| ID | Model | Adres | Lokalizacja | I/O | +|:---|:----|:---------|:--------|----:| +| rs.0.id.39 | IB-CTRL-IO-RS485 | id.39 | Basia | 10 | +| rs.0.id.40 | IB-CTRL-IO-RS485 | id.40 | Biuro A | 10 | +| rs.0.id.35 | IB-CTRL-IO-RS485 | id.35 | Biuro W/ Garderoba | 10 | +| rs.0.id.5 | IB-CTRL-IO-RS485 | id.10 | ID10 Sterownik kominka | 10 | +| rs.0.id.2 | IB-CTRL-IO-RS485 | id.2 | ID2 Sterownik ogrzewania podłogowego | 10 | +| rs.0.id.3 | IB-CTRL-IO-RS485 | id.3 | ID3 | 10 | +| rs.0.id.4 | IB-CTRL-IO-RS485 | id.4 | ID4 | 10 | +| rs.0.id.6 | IB-CTRL-IO-RS485 | id.6 | ID6 | 10 | +| rs.0.id.32 | IB-CTRL-IO-RS485 | id.32 | Jadalnia / Salon | 10 | +| rs.0.id.34 | IB-CTRL-IO-RS485 | id.34 | Korytarz | 10 | +| rs.0.id.31 | IB-CTRL-IO-RS485 | id.31 | Kuchnia | 10 | +| rs.0.id.33 | IB-CTRL-IO-RS485 | id.33 | Salon | 10 | +| rs.0.id.36 | IB-CTRL-IO-RS485 | id.36 | Sypialnia | 10 | +| rs.0.id.41 | IB-CTRL-IO-RS485 | id.41 | WC/Poddasze | 10 | +| rs.0.id.30 | IB-CTRL-IO-RS485 | id.30 | Wiatrołap | 10 | +| rs.0.id.37 | IB-CTRL-IO-RS485 | id.37 | Łazienka | 10 | +| rs.0.id.38 | IB-CTRL-IO-RS485 | id.38 | Łazienka/WC | 10 | + +## Szczegóły urządzeń + +### rs.0.id.39 + +**Sterownik I/O oświetlenia pokoju Basi.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.39 +- Lokalizacja: Basia +- Lokalizacja: Basia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk D1 | +| input.t.1 | input | ✅ | Przycisk D2 | +| input.t.2 | input | ✅ | Przycisk D3 | +| input.t.3 | input | ✅ | Przycisk D4 | +| output.do.0 | output | ✅ | Oświetlenie D1 główne | +| output.do.1 | output | ✅ | Oświetlenie D2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie D3 chmurka | +| output.do.3 | output | ✅ | Oświetlenie D4 łóżko | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 | + +### rs.0.id.40 + +**Sterownik I/O oświetlenia biura A.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.40 +- Lokalizacja: Biuro A +- Lokalizacja: Biuro A + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk B1 | +| input.t.1 | input | ✅ | Przycisk B2 | +| input.t.2 | input | ⚫ | Wolne wejście | +| input.t.3 | input | ✅ | Przycisk B4 | +| output.do.0 | output | ✅ | Oświetlenie B1 główne | +| output.do.1 | output | ✅ | Oświetlenie B2 nad biurkiem | +| output.do.2 | output | ✅ | Oświetlenie B3 biurko lampa | +| output.do.3 | output | ✅ | Oświetlenie B4 dla ledów | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 | + +### rs.0.id.35 + +**Sterownik I/O oświetlenia biura/garderoby.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.35 +- Lokalizacja: Biuro W/ Garderoba +- Lokalizacja: Biuro W/ Garderoba + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk BW1 | +| input.t.1 | input | ✅ | Przycisk BW2 | +| input.t.2 | input | ✅ | Przycisk G1 | +| input.t.3 | input | ✅ | Przycisk G2 | +| output.do.0 | output | ✅ | Oświetlenie BW1 | +| output.do.1 | output | ✅ | Oświetlenie BW2 | +| output.do.2 | output | ✅ | Oświetlenie G1 | +| output.do.3 | output | ✅ | Oświetlenie G2 led nad szafami i koło lustra | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 | + +### rs.0.id.5 + +**Sterownik ID10 .** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.10 +- Lokalizacja: ID10 Sterownik kominka +- Lokalizacja: ID10 Sterownik kominka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. zasialnia kominka | +| input.t.1 | input | ✅ | czujnik temp. w zbiorniku buforowym na dole | +| input.t.2 | input | ✅ | brak czujnika | +| input.t.3 | input | ✅ | brak czujnika | +| output.do.0 | output | ✅ | pompa obiegowa kominka | +| output.do.1 | output | ✅ | | +| output.do.2 | output | ✅ | | +| output.do.3 | output | ✅ | | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.2 + +**Sterownik ID2 Sterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.2 +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego +- Lokalizacja: ID2 Sterownik ogrzewania podłogowego + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | XXX | +| input.t.1 | input | ✅ | XXX | +| input.t.2 | input | ✅ | XXX | +| input.t.3 | input | ✅ | XXX | +| output.do.0 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) | +| output.do.1 | output | ✅ | zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] | +| output.do.2 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) | +| output.do.3 | output | ✅ | zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.3 + +**Sterownik ID3 syterownik ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.3 +- Lokalizacja: ID3 +- Lokalizacja: ID3 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Basia | +| input.t.1 | input | ✅ | czujnik temp. Ania | +| input.t.2 | input | ✅ | czujnik temp. WC | +| input.t.3 | input | ✅ | czujnik temp. Wiatrołap | +| output.do.0 | output | ✅ | siłownik rozdzielacz R1 - Basia | +| output.do.1 | output | ✅ | siłownik rozdzielacz R1 - Ania | +| output.do.2 | output | ✅ | siłownik pokoju - WC | +| output.do.3 | output | ✅ | siłownik pokoju - Wiatrołap | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.4 + +**Sterownik ID4 ogrzewania podłogowego.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.4 +- Lokalizacja: ID4 +- Lokalizacja: ID4 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | czujnik temp. Salon | +| input.t.1 | input | ✅ | czujnik temp. Biuro Wojtek | +| input.t.2 | input | ✅ | czujnik temp. Sypialnia | +| input.t.3 | input | ✅ | czujnik temp. Duża łazienka | +| output.do.0 | output | ✅ | siłownik rozdzielacz R2 - salon | +| output.do.1 | output | ✅ | siłownik rozdzielacz R2 - biuro Wojtek | +| output.do.2 | output | ✅ | siłownik rozdzielacz R2 - sypialnia | +| output.do.3 | output | ✅ | siłownik rozdzielacz R2 - duża łazienka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.6 + +**Sterownik ID6 do sterowania nawadnianiem.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.6 +- Lokalizacja: ID6 +- Lokalizacja: ID6 + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | | +| input.t.1 | input | ✅ | | +| input.t.2 | input | ✅ | | +| input.t.3 | input | ✅ | | +| output.do.0 | output | ✅ | pompa głębinowa | +| output.do.1 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.2 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.do.3 | output | ✅ | elektro zawór zraszaczy sekcja X | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.32 + +**Sterownik I/O oświetlenia jadalni/salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.32 +- Lokalizacja: Jadalnia / Salon +- Lokalizacja: Jadalnia / Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk J1 | +| input.t.1 | input | ✅ | Przycisk J2 | +| input.t.2 | input | ✅ | Przycisk S1 | +| input.t.3 | input | ✅ | Przycisk S2 | +| output.do.0 | output | ✅ | Oświetlenie J1 | +| output.do.1 | output | ✅ | Oświetlenie J2 | +| output.do.2 | output | ✅ | Oświetlenie S1 Ring | +| output.do.3 | output | ✅ | Oświetlenie S2 lampy za kanapą | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 | + +### rs.0.id.34 + +**Sterownik I/O oświetlenia korytarza.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.34 +- Lokalizacja: Korytarz +- Lokalizacja: Korytarz + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H3 | +| input.t.1 | input | ✅ | Przycisk H4 | +| input.t.2 | input | ✅ | Przycisk H5 | +| input.t.3 | input | ✅ | Przycisk H6 | +| output.do.0 | output | ✅ | Oświetlenie H3 szynoprzewód nowodworski | +| output.do.1 | output | ✅ | Oświetlenie H4 szynoprzewód nowodworski | +| output.do.2 | output | ✅ | Oświetlenie H5 ledy pionowe | +| output.do.3 | output | ✅ | Oświetlenie H6 led kominek | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 | + +### rs.0.id.31 + +**Sterownik I/O oświetlenia kuchni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.31 +- Lokalizacja: Kuchnia +- Lokalizacja: Kuchnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk K3 | +| input.t.1 | input | ✅ | Przycisk K4 | +| input.t.2 | input | ✅ | Przycisk K5 | +| input.t.3 | input | ✅ | Przycisk K6 | +| output.do.0 | output | ✅ | Oświetlenie K3 halogeny okno | +| output.do.1 | output | ✅ | Oświetlenie K4 lampy nad barem | +| output.do.2 | output | ✅ | Oświetlenie K5 półki led | +| output.do.3 | output | ✅ | Oświetlenie K6 led okno | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 | + +### rs.0.id.33 + +**Sterownik I/O oświetlenia salonu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.33 +- Lokalizacja: Salon +- Lokalizacja: Salon + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk S3 | +| input.t.1 | input | ✅ | Przycisk S4 | +| input.t.2 | input | ✅ | Przycisk S5 | +| input.t.3 | input | ✅ | Przycisk S6 | +| output.do.0 | output | ✅ | Oświetlenie lampa przed tv | +| output.do.1 | output | ✅ | Oświetlenie led | +| output.do.2 | output | ✅ | Oświetlenie dekoracyjne koło lampy | +| output.do.3 | output | ✅ | Oświetlenie led sufit wnęka | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 | + +### rs.0.id.36 + +**Sterownik I/O oświetlenia sypialni.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.36 +- Lokalizacja: Sypialnia +- Lokalizacja: Sypialnia + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk R1 | +| input.t.1 | input | ✅ | Przycisk R2 | +| input.t.2 | input | ✅ | Przycisk R3 | +| input.t.3 | input | ✅ | Przycisk R4 | +| output.do.0 | output | ✅ | Oświetlenie R1 główne | +| output.do.1 | output | ✅ | Oświetlenie R2 nakastlik P | +| output.do.2 | output | ✅ | Oświetlenie R3 nakastlik L | +| output.do.3 | output | ✅ | Oświetlenie R4 led na suficie | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 | + +### rs.0.id.41 + +**Sterownik I/O oświetlenia WC/poddasze.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.41 +- Lokalizacja: WC/Poddasze +- Lokalizacja: WC/Poddasze + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk W2 góra halogeny | +| input.t.1 | input | ✅ | Przycisk W3 halogen prysznic | +| input.t.2 | input | ✅ | Przycisk P1 poddasze 1 | +| input.t.3 | input | ✅ | Przycisk P2 Poddasze 2 | +| output.do.0 | output | ✅ | Oświetlenie W2 góra halogeny | +| output.do.1 | output | ✅ | Oświetlenie W3 halogen prysznic + led | +| output.do.2 | output | ✅ | Oświetlenie P1 Poddasze 1 | +| output.do.3 | output | ✅ | Oświetlenie P2 Poddasze 2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. | + +### rs.0.id.30 + +**Sterownik I/O oświetlenia wiatrołapu.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.30 +- Lokalizacja: Wiatrołap +- Lokalizacja: Wiatrołap + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk H1 - sterowanie Led bar AP | +| input.t.1 | input | ✅ | Przycisk H2 | +| input.t.2 | input | ✅ | Przycisk K1 | +| input.t.3 | input | ✅ | Przycisk K2 | +| output.do.0 | output | ✅ | Oświetlenie H1 (Led bar AP) | +| output.do.1 | output | ✅ | Oświetlenie H2 led | +| output.do.2 | output | ✅ | Oświetlenie K1 szynoprzewód nowodworski | +| output.do.3 | output | ✅ | Oświetlenie K2 szynoprzewód nowodworski | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 | + +### rs.0.id.37 + +**Sterownik I/O oświetlenia łazienki.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.37 +- Lokalizacja: Łazienka +- Lokalizacja: Łazienka + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ✅ | Przycisk L1 | +| input.t.1 | input | ✅ | Przycisk L2 | +| input.t.2 | input | ✅ | Przycisk L3 | +| input.t.3 | input | ✅ | Przycisk L4 | +| output.do.0 | output | ✅ | Oświetlenie L1 | +| output.do.1 | output | ✅ | Oświetlenie L2 | +| output.do.2 | output | ✅ | Oświetlenie L3 | +| output.do.3 | output | ✅ | Oświetlenie L4 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 | + +### rs.0.id.38 + +**Sterownik I/O oświetlenia łazienki/WC.** + +- Model: IB-CTRL-IO-RS485 +- Adres: id.38 +- Lokalizacja: Łazienka/WC +- Lokalizacja: Łazienka/WC + +| I/O | Typ | Status | Opis | +|:----|:----|:------:|:-----| +| input.t.0 | input | ⚫ | Wolne wejście | +| input.t.1 | input | ✅ | Przycisk L6 | +| input.t.2 | input | ✅ | Przycisk W1 | +| input.t.3 | input | ✅ | Przycisk W2 | +| output.do.0 | output | ✅ | Oświetlenie L5 | +| output.do.1 | output | ✅ | Oświetlenie L6 | +| output.do.2 | output | ✅ | Oświetlenie W1 | +| output.do.3 | output | ✅ | Oświetlenie W2 | +| output.px.0 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 | +| output.px.1 | output | ⚫ | Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 | + +## Legenda statusów + +- ✅ `ok` - Połączenie działa poprawnie +- ❌ `err` - Błąd połączenia +- ⚫ `nc` - Niepodłączone +- ❓ `??` - Status nieznany +- ⚠️ `!` - Do zrobienia/sprawdzenia diff --git a/ib_manager.py b/ib_manager.py new file mode 100644 index 0000000..f9080ae --- /dev/null +++ b/ib_manager.py @@ -0,0 +1,462 @@ +#!/usr/bin/env python3 +""" +IB System Documentation Manager +Skrypt do parsowania, modyfikowania i generowania raportów z dokumentacji YAML. +""" + +import yaml +import csv +import json +import argparse +from pathlib import Path +from datetime import datetime +from typing import Dict, List, Optional, Any +from dataclasses import dataclass, field + + +@dataclass +class IOPoint: + io_id: str + status: str + mapping: str + description: str + + def to_dict(self) -> dict: + return {'io_id': self.io_id, 'status': self.status, 'mapping': self.mapping, 'description': self.description} + + +@dataclass +class Device: + device_id: str + model_id: str + location: str + description: str + bus_id: str + address: str + inputs: List[IOPoint] = field(default_factory=list) + outputs: List[IOPoint] = field(default_factory=list) + + def to_dict(self) -> dict: + return { + 'device_id': self.device_id, 'model_id': self.model_id, 'location': self.location, + 'description': self.description, 'bus_id': self.bus_id, 'address': self.address, + 'inputs': [io.to_dict() for io in self.inputs], + 'outputs': [io.to_dict() for io in self.outputs] + } + + +class IBDocumentManager: + def __init__(self, yaml_path: str): + self.yaml_path = Path(yaml_path) + self.data: Dict = {} + self.devices: Dict[str, Device] = {} + self.load() + + def load(self) -> None: + if not self.yaml_path.exists(): + raise FileNotFoundError(f"Plik nie istnieje: {self.yaml_path}") + with open(self.yaml_path, 'r', encoding='utf-8') as f: + self.data = yaml.safe_load(f) + self._parse_devices() + print(f"✓ Wczytano: {self.yaml_path}") + print(f" Projekt: {self.data['project'].get('title', 'N/A')}") + print(f" Urządzeń: {len(self.devices)}") + + def _parse_devices(self) -> None: + self.devices.clear() + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev_data in hw_spec.get('devices', []): + device_id = dev_data.get('device_id', '') + connections = dev_data.get('connections', []) + bus_id = connections[0].get('bus_id', '') if connections else '' + address = connections[0].get('address', '') if connections else '' + inputs, outputs = [], [] + for io_data in dev_data.get('io', []): + io_point = IOPoint( + io_id=io_data.get('io_id', ''), status=io_data.get('status', ''), + mapping=io_data.get('mapping', ''), description=io_data.get('description', '') + ) + if 'input' in io_point.io_id: + inputs.append(io_point) + else: + outputs.append(io_point) + device = Device( + device_id=device_id, model_id=dev_data.get('model_id', ''), + location=dev_data.get('location', ''), description=dev_data.get('description', '').strip(), + bus_id=bus_id, address=address, inputs=inputs, outputs=outputs + ) + self.devices[device_id] = device + + def save(self, output_path: Optional[str] = None) -> None: + path = Path(output_path) if output_path else self.yaml_path + self.data['project']['updated_at'] = datetime.now().strftime('%Y-%m-%d') + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"✓ Zapisano: {path}") + + def _get_device_category(self, device: 'Device') -> str: + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + return 'OSWIETLENIE' + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower or 'komink' in desc_lower: + return 'OGRZEWANIE' + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower or 'pompa' in desc_lower: + return 'NAWADNIANIE' + else: + return 'INNE' + + def _sort_devices_by_id(self, devices: List['Device']) -> List['Device']: + def get_numeric_id(dev): + try: + return int(dev.address.split('.')[-1]) + except: + return 999 + return sorted(devices, key=get_numeric_id) + + def _get_device_stats(self, device: 'Device') -> dict: + inputs_ok = sum(1 for io in device.inputs if io.status == 'ok') + outputs_do_ok = sum(1 for io in device.outputs if 'do' in io.io_id and io.status == 'ok') + total_inputs = len(device.inputs) + total_do = sum(1 for io in device.outputs if 'do' in io.io_id) + return { + 'inputs_ok': inputs_ok, 'total_inputs': total_inputs, + 'outputs_do_ok': outputs_do_ok, 'total_do': total_do, + 'status': 'OK' if inputs_ok == total_inputs and outputs_do_ok == total_do else '!!' + } + + def report_stats(self) -> None: + """Wyświetla statystyki projektu""" + total_inputs = sum(len(d.inputs) for d in self.devices.values()) + total_outputs = sum(len(d.outputs) for d in self.devices.values()) + ok_inputs = sum(1 for d in self.devices.values() for io in d.inputs if io.status == "ok") + ok_outputs = sum(1 for d in self.devices.values() for io in d.outputs if io.status == "ok") + print(f"\n=== STATYSTYKI PROJEKTU ===") + print(f"Urządzeń: {len(self.devices)}") + print(f"Wejść: {total_inputs} (OK: {ok_inputs})") + print(f"Wyjść: {total_outputs} (OK: {ok_outputs})") + print(f"Razem I/O: {total_inputs + total_outputs}") + + def report_connections(self) -> str: + lines = ["# SCHEMAT POLACZEN - PRZYCISKI -> WYJSCIA", f"Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", "", "=" * 100] + for device_id, device in sorted(self.devices.items()): + lines.extend(["", f"## {device.location} ({device.device_id})", f" Adres: {device.bus_id}.{device.address}", "-" * 80]) + for inp in device.inputs: + if inp.io_id.startswith('input.t.'): + idx = inp.io_id.split('.')[-1] + out = next((o for o in device.outputs if o.io_id == f'output.do.{idx}'), None) + inp_desc = inp.description[:35] if inp.description else '-' + out_desc = out.description[:35] if out and out.description else '-' + lines.append(f"{inp.io_id:<15} [{inp.status:<4}] {inp_desc}") + lines.append(f" --> output.do.{idx:<6} [{out.status if out else '-':<4}] {out_desc}") + return "\n".join(lines) + + def report_summary_table(self) -> str: + lines = [ + "", + "=" * 82, + " PODSUMOWANIE STEROWNIKOW ", + f" Wygenerowano: {datetime.now().strftime('%Y-%m-%d %H:%M')}", + "=" * 82, + "" + ] + + categories = {} + for device in self.devices.values(): + cat = self._get_device_category(device) + if cat not in categories: + categories[cat] = [] + categories[cat].append(device) + + cat_order = ['OSWIETLENIE', 'OGRZEWANIE', 'NAWADNIANIE', 'INNE'] + cat_icons = {'OSWIETLENIE': '[L]', 'OGRZEWANIE': '[H]', 'NAWADNIANIE': '[W]', 'INNE': '[?]'} + + for cat_name in cat_order: + if cat_name not in categories: + continue + + devices = self._sort_devices_by_id(categories[cat_name]) + + lines.append(f"+--- {cat_icons[cat_name]} {cat_name} ({len(devices)} szt.) " + "-" * (55 - len(cat_name))) + lines.append("|") + lines.append("| ID | Lokalizacja | Wejscia | Wyjscia | Status") + lines.append("| ------+----------------------------------+---------+---------+-------") + + for device in devices: + stats = self._get_device_stats(device) + id_num = device.address.split('.')[-1] + loc = device.location[:32].ljust(32) + inp = f"{stats['inputs_ok']}/{stats['total_inputs']}" + out = f"{stats['outputs_do_ok']}/{stats['total_do']}" + + lines.append(f"| {id_num:>4} | {loc} | {inp:^7} | {out:^7} | {stats['status']}") + + lines.append("|") + + lines.append("+" + "-" * 81) + lines.extend([ + "", + "LEGENDA:", + " [L] Oswietlenie [H] Ogrzewanie [W] Nawadnianie [?] Inne", + " OK - Wszystkie wejscia/wyjscia aktywne", + " !! - Niektore wejscia/wyjscia nieaktywne lub blad", + " Wejscia = aktywne czujniki/przyciski", + " Wyjscia = aktywne wyjscia cyfrowe (DO)" + ]) + + return "\n".join(lines) + + def report_full_io_table(self) -> str: + lines = ["# PELNA LISTA PUNKTOW I/O", "", "| Sterownik | Lokalizacja | Typ | IO_ID | Status | Opis |", "|:----------|:------------|:----|:------|:-------|:-----|"] + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + lines.append(f"| {device.address} | {device.location[:15]} | IN | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + for io in device.outputs: + lines.append(f"| {device.address} | {device.location[:15]} | OUT | {io.io_id} | {io.status} | {io.description[:40] if io.description else '-'} |") + return "\n".join(lines) + + def report_by_function(self) -> str: + categories = {'oswietlenie': [], 'ogrzewanie': [], 'nawadnianie': [], 'inne': []} + for device_id, device in self.devices.items(): + desc_lower = device.description.lower() + loc_lower = device.location.lower() + if 'oświetleni' in desc_lower or any(x in loc_lower for x in ['wiatrołap', 'kuchnia', 'salon', 'korytarz', 'biuro', 'sypialnia', 'łazienka', 'wc', 'basia', 'poddasze', 'jadalnia', 'garderoba']): + categories['oswietlenie'].append(device) + elif 'ogrzewan' in desc_lower or 'temp' in desc_lower: + categories['ogrzewanie'].append(device) + elif 'nawadnian' in desc_lower or 'zraszacz' in desc_lower: + categories['nawadnianie'].append(device) + else: + categories['inne'].append(device) + lines = ["# URZADZENIA WEDLUG FUNKCJI", ""] + for cat_name, devices in categories.items(): + if devices: + lines.append(f"\n## {cat_name.upper()} ({len(devices)} urzadzen)") + for dev in self._sort_devices_by_id(devices): + lines.append(f" * {dev.address.split('.')[-1]:>3}: {dev.location}") + return "\n".join(lines) + + def generate_mermaid_diagram(self) -> str: + lines = ["```mermaid", "graph TD", " subgraph RS485[Magistrala RS485]"] + for device_id, device in self.devices.items(): + addr = device.address.replace('.', '_') + lines.append(f' DEV_{addr}["{device.address}
{device.location}"]') + lines.extend([" end", "```"]) + return "\n".join(lines) + + def export_csv(self, output_path: str) -> None: + with open(output_path, 'w', newline='', encoding='utf-8') as f: + writer = csv.writer(f, delimiter=';') + writer.writerow(['device_id', 'address', 'location', 'io_type', 'io_id', 'status', 'mapping', 'description']) + for device_id, device in sorted(self.devices.items()): + for io in device.inputs: + writer.writerow([device.device_id, device.address, device.location, 'INPUT', io.io_id, io.status, io.mapping, io.description]) + for io in device.outputs: + writer.writerow([device.device_id, device.address, device.location, 'OUTPUT', io.io_id, io.status, io.mapping, io.description]) + print(f"Eksportowano CSV: {output_path}") + + def export_json(self, output_path: str) -> None: + data = {'project': {'id': self.data['project'].get('id'), 'title': self.data['project'].get('title'), 'generated_at': datetime.now().isoformat()}, 'devices': [dev.to_dict() for dev in self.devices.values()]} + with open(output_path, 'w', encoding='utf-8') as f: + json.dump(data, f, ensure_ascii=False, indent=2) + print(f"Eksportowano JSON: {output_path}") + + def export_markdown(self, output_path: str) -> None: + """Eksport pełnej dokumentacji do formatu Markdown""" + md_lines = [] + proj = self.data.get('project', {}) + + md_lines.append(f"# {proj.get('name', 'Projekt')}") + md_lines.append("") + if proj.get('description'): + md_lines.append(f"**Opis:** {proj['description']}") + if proj.get('version'): + md_lines.append(f"**Wersja:** {proj['version']}") + if proj.get('last_update'): + md_lines.append(f"**Ostatnia aktualizacja:** {proj['last_update']}") + md_lines.append("") + + hw_spec = proj.get('hardware_specification', {}) + if 'bus' in hw_spec: + bus = hw_spec['bus'] + md_lines.append("## Specyfikacja magistrali") + md_lines.append("") + md_lines.append(f"- **Typ:** {bus.get('type', 'N/A')}") + md_lines.append(f"- **ID:** {bus.get('bus_id', 'N/A')}") + md_lines.append(f"- **Prędkość:** {bus.get('baud_rate', 'N/A')} bps") + md_lines.append(f"- **Parametry:** {bus.get('data_bits', '?')}{bus.get('parity', '?')}{bus.get('stop_bits', '?')}") + md_lines.append("") + + md_lines.append("## Statystyki") + md_lines.append("") + md_lines.append(f"- **Liczba urządzeń:** {len(self.devices)}") + total_io = sum(len(d.inputs) + len(d.outputs) for d in self.devices.values()) + md_lines.append(f"- **Łączna liczba I/O:** {total_io}") + md_lines.append("") + + md_lines.append("## Lista urządzeń") + md_lines.append("") + md_lines.append("| ID | Model | Adres | Lokalizacja | I/O |") + md_lines.append("|:---|:----|:---------|:--------|----:|") + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + io_count = len(dev.inputs + dev.outputs) + md_lines.append(f"| {dev.device_id} | {dev.model_id or 'N/A'} | {dev.address or 'N/A'} | {dev.location or 'N/A'} | {io_count} |") + md_lines.append("") + + md_lines.append("## Szczegóły urządzeń") + md_lines.append("") + + for dev in sorted(self.devices.values(), key=lambda d: (d.location or "", d.device_id)): + md_lines.append(f"### {dev.device_id}") + md_lines.append("") + if dev.description: + md_lines.append(f"**{dev.description}**") + md_lines.append("") + md_lines.append(f"- Model: {dev.model_id or 'N/A'}") + md_lines.append(f"- Adres: {dev.address or 'N/A'}") + md_lines.append(f"- Lokalizacja: {dev.location or 'N/A'}") + if dev.location: + md_lines.append(f"- Lokalizacja: {dev.location}") + md_lines.append("") + + if dev.inputs + dev.outputs: + md_lines.append("| I/O | Typ | Status | Opis |") + md_lines.append("|:----|:----|:------:|:-----|") + for io in dev.inputs + dev.outputs: + status_icon = {'ok': '✅', 'err': '❌', 'nc': '⚫', '??': '❓', '!': '⚠️'}.get(io.status, io.status) + desc = io.description.replace('|', '\\|') if io.description else '' + io_type = io.io_id.split(".")[0] if "." in io.io_id else "io" + md_lines.append(f"| {io.io_id} | {io_type} | {status_icon} | {desc} |") + md_lines.append("") + + md_lines.append("## Legenda statusów") + md_lines.append("") + md_lines.append("- ✅ `ok` - Połączenie działa poprawnie") + md_lines.append("- ❌ `err` - Błąd połączenia") + md_lines.append("- ⚫ `nc` - Niepodłączone") + md_lines.append("- ❓ `??` - Status nieznany") + md_lines.append("- ⚠️ `!` - Do zrobienia/sprawdzenia") + md_lines.append("") + + with open(output_path, 'w', encoding='utf-8') as f: + f.write('\n'.join(md_lines)) + print(f"Eksportowano Markdown: {output_path}") + + def update_io_description(self, device_id: str, io_id: str, new_description: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['description'] = new_description + self._parse_devices() + print(f"Zaktualizowano: {device_id}/{io_id}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def update_io_status(self, device_id: str, io_id: str, new_status: str) -> bool: + hw_spec = self.data.get('project', {}).get('hardware_specification', {}) + for dev in hw_spec.get('devices', []): + if dev.get('device_id') == device_id: + for io in dev.get('io', []): + if io.get('io_id') == io_id: + io['status'] = new_status + self._parse_devices() + print(f"Status zmieniony: {device_id}/{io_id} -> {new_status}") + return True + print(f"Nie znaleziono: {device_id}/{io_id}") + return False + + def save(self, output_path: str = None) -> None: + path = output_path or self.file_path + with open(path, 'w', encoding='utf-8') as f: + yaml.dump(self.data, f, allow_unicode=True, default_flow_style=False, sort_keys=False) + print(f"Zapisano: {path}") + + +def main(): + parser = argparse.ArgumentParser(description='IB Documentation Manager') + parser.add_argument('file', help='Plik YAML z dokumentacją') + parser.add_argument('--stats', action='store_true', help='Pokaż statystyki') + parser.add_argument('--report', choices=['summary', 'connections'], help='Generuj raport') + parser.add_argument('--search', help='Szukaj frazy w opisach') + parser.add_argument('--export-csv', metavar='FILE', help='Eksport do CSV') + parser.add_argument('--export-json', metavar='FILE', help='Eksport do JSON') + parser.add_argument('--export-md', metavar='FILE', help='Eksport do Markdown') + parser.add_argument('--interactive', '-i', action='store_true', help='Tryb interaktywny') + args = parser.parse_args() + + manager = IBDocumentManager(args.file) + + if args.stats: + manager.report_stats() + elif args.report == 'summary': + print(manager.report_summary_table()) + elif args.report == 'connections': + print(manager.report_connections()) + elif args.search: + manager.search_description(args.search) + elif args.export_csv: + manager.export_csv(args.export_csv) + elif args.export_json: + manager.export_json(args.export_json) + elif args.export_md: + manager.export_markdown(args.export_md) + elif args.interactive: + print("\nTryb interaktywny. Komendy: stats, summary, connections, search, export, edit, save, quit") + while True: + try: + command = input("\n> ").strip().lower() + except EOFError: + break + + if command in ('quit', 'exit', 'q'): + break + elif command == 'stats': + manager.report_stats() + elif command == 'summary': + print(manager.report_summary_table()) + elif command == 'connections': + print(manager.report_connections()) + elif command == 'search': + phrase = input("Fraza: ").strip() + manager.search_description(phrase) + elif command == 'export': + print("Format: csv, json, md") + fmt = input("Format: ").strip().lower() + filename = input("Nazwa pliku: ").strip() + if fmt == 'csv': + manager.export_csv(filename) + elif fmt == 'json': + manager.export_json(filename) + elif fmt == 'md': + manager.export_markdown(filename) + elif command == 'edit': + print("\nOpcje edycji: desc, status") + edit_type = input("Typ edycji: ").strip().lower() + if edit_type == 'desc': + device_id = input("Device ID (np. rs.0.id.30): ").strip() + io_id = input("IO ID (np. input.t.0): ").strip() + new_desc = input("Nowy opis: ").strip() + manager.update_io_description(device_id, io_id, new_desc) + elif edit_type == 'status': + device_id = input("Device ID: ").strip() + io_id = input("IO ID: ").strip() + new_status = input("Nowy status (ok/err/nc/??/!): ").strip() + manager.update_io_status(device_id, io_id, new_status) + elif command == 'save': + filename = input("Nazwa pliku (Enter = nadpisz oryginalny): ").strip() + manager.save(filename if filename else None) + elif command == 'help': + print("Komendy: stats, summary, connections, search, export, edit, save, quit") + else: + print("Nieznana komenda. Wpisz 'help' dla pomocy.") + else: + parser.print_help() + + return 0 + + +if __name__ == '__main__': + exit(main()) diff --git a/io_connections.csv b/io_connections.csv new file mode 100644 index 0000000..75010ba --- /dev/null +++ b/io_connections.csv @@ -0,0 +1,171 @@ +device_id;address;location;io_type;io_id;status;mapping;description +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.0;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.1;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.2;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;INPUT;input.t.3;ok;;XXX +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.0;ok;;zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.1;ok;;zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.2;ok;;zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu) +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.do.3;ok;;zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor] +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0 +rs.0.id.2;id.2;ID2 Sterownik ogrzewania podłogowego;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.3;id.3;ID3;INPUT;input.t.0;ok;;czujnik temp. Basia +rs.0.id.3;id.3;ID3;INPUT;input.t.1;ok;;czujnik temp. Ania +rs.0.id.3;id.3;ID3;INPUT;input.t.2;ok;;czujnik temp. WC +rs.0.id.3;id.3;ID3;INPUT;input.t.3;ok;;czujnik temp. Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R1 - Basia +rs.0.id.3;id.3;ID3;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R1 - Ania +rs.0.id.3;id.3;ID3;OUTPUT;output.do.2;ok;;siłownik pokoju - WC +rs.0.id.3;id.3;ID3;OUTPUT;output.do.3;ok;;siłownik pokoju - Wiatrołap +rs.0.id.3;id.3;ID3;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0 +rs.0.id.3;id.3;ID3;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.0;ok;;Przycisk H1 - sterowanie Led bar AP +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.1;ok;;Przycisk H2 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.2;ok;;Przycisk K1 +rs.0.id.30;id.30;Wiatrołap;INPUT;input.t.3;ok;;Przycisk K2 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.0;ok;;Oświetlenie H1 (Led bar AP) +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.1;ok;;Oświetlenie H2 led +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.2;ok;;Oświetlenie K1 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.do.3;ok;;Oświetlenie K2 szynoprzewód nowodworski +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px0 +rs.0.id.30;id.30;Wiatrołap;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.30.px1 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.0;ok;;Przycisk K3 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.1;ok;;Przycisk K4 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.2;ok;;Przycisk K5 +rs.0.id.31;id.31;Kuchnia;INPUT;input.t.3;ok;;Przycisk K6 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.0;ok;;Oświetlenie K3 halogeny okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.1;ok;;Oświetlenie K4 lampy nad barem +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.2;ok;;Oświetlenie K5 półki led +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.do.3;ok;;Oświetlenie K6 led okno +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px0 +rs.0.id.31;id.31;Kuchnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.31.px1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.0;ok;;Przycisk J1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.1;ok;;Przycisk J2 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.2;ok;;Przycisk S1 +rs.0.id.32;id.32;Jadalnia / Salon;INPUT;input.t.3;ok;;Przycisk S2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.0;ok;;Oświetlenie J1 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.1;ok;;Oświetlenie J2 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.2;ok;;Oświetlenie S1 Ring +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.do.3;ok;;Oświetlenie S2 lampy za kanapą +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px0 +rs.0.id.32;id.32;Jadalnia / Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.32.px1 +rs.0.id.33;id.33;Salon;INPUT;input.t.0;ok;;Przycisk S3 +rs.0.id.33;id.33;Salon;INPUT;input.t.1;ok;;Przycisk S4 +rs.0.id.33;id.33;Salon;INPUT;input.t.2;ok;;Przycisk S5 +rs.0.id.33;id.33;Salon;INPUT;input.t.3;ok;;Przycisk S6 +rs.0.id.33;id.33;Salon;OUTPUT;output.do.0;ok;;Oświetlenie lampa przed tv +rs.0.id.33;id.33;Salon;OUTPUT;output.do.1;ok;;Oświetlenie led +rs.0.id.33;id.33;Salon;OUTPUT;output.do.2;ok;;Oświetlenie dekoracyjne koło lampy +rs.0.id.33;id.33;Salon;OUTPUT;output.do.3;ok;;Oświetlenie led sufit wnęka +rs.0.id.33;id.33;Salon;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px0 +rs.0.id.33;id.33;Salon;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.33.px1 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.0;ok;;Przycisk H3 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.1;ok;;Przycisk H4 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.2;ok;;Przycisk H5 +rs.0.id.34;id.34;Korytarz;INPUT;input.t.3;ok;;Przycisk H6 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.0;ok;;Oświetlenie H3 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.1;ok;;Oświetlenie H4 szynoprzewód nowodworski +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.2;ok;;Oświetlenie H5 ledy pionowe +rs.0.id.34;id.34;Korytarz;OUTPUT;output.do.3;ok;;Oświetlenie H6 led kominek +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px0 +rs.0.id.34;id.34;Korytarz;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.34.px1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.0;ok;;Przycisk BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.1;ok;;Przycisk BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.2;ok;;Przycisk G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;INPUT;input.t.3;ok;;Przycisk G2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.0;ok;;Oświetlenie BW1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.1;ok;;Oświetlenie BW2 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.2;ok;;Oświetlenie G1 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.do.3;ok;;Oświetlenie G2 led nad szafami i koło lustra +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px0 +rs.0.id.35;id.35;Biuro W/ Garderoba;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.35.px1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.0;ok;;Przycisk R1 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.1;ok;;Przycisk R2 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.2;ok;;Przycisk R3 +rs.0.id.36;id.36;Sypialnia;INPUT;input.t.3;ok;;Przycisk R4 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.0;ok;;Oświetlenie R1 główne +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.1;ok;;Oświetlenie R2 nakastlik P +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.2;ok;;Oświetlenie R3 nakastlik L +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.do.3;ok;;Oświetlenie R4 led na suficie +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px0 +rs.0.id.36;id.36;Sypialnia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.36.px1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.0;ok;;Przycisk L1 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.1;ok;;Przycisk L2 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.2;ok;;Przycisk L3 +rs.0.id.37;id.37;Łazienka;INPUT;input.t.3;ok;;Przycisk L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.0;ok;;Oświetlenie L1 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.1;ok;;Oświetlenie L2 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.2;ok;;Oświetlenie L3 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.do.3;ok;;Oświetlenie L4 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px0 +rs.0.id.37;id.37;Łazienka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.37.px1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.0;nc;;Wolne wejście +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.1;ok;;Przycisk L6 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.2;ok;;Przycisk W1 +rs.0.id.38;id.38;Łazienka/WC;INPUT;input.t.3;ok;;Przycisk W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.0;ok;;Oświetlenie L5 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.1;ok;;Oświetlenie L6 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.2;ok;;Oświetlenie W1 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.do.3;ok;;Oświetlenie W2 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px0 +rs.0.id.38;id.38;Łazienka/WC;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.38.px1 +rs.0.id.39;id.39;Basia;INPUT;input.t.0;ok;;Przycisk D1 +rs.0.id.39;id.39;Basia;INPUT;input.t.1;ok;;Przycisk D2 +rs.0.id.39;id.39;Basia;INPUT;input.t.2;ok;;Przycisk D3 +rs.0.id.39;id.39;Basia;INPUT;input.t.3;ok;;Przycisk D4 +rs.0.id.39;id.39;Basia;OUTPUT;output.do.0;ok;;Oświetlenie D1 główne +rs.0.id.39;id.39;Basia;OUTPUT;output.do.1;ok;;Oświetlenie D2 nad biurkiem +rs.0.id.39;id.39;Basia;OUTPUT;output.do.2;ok;;Oświetlenie D3 chmurka +rs.0.id.39;id.39;Basia;OUTPUT;output.do.3;ok;;Oświetlenie D4 łóżko +rs.0.id.39;id.39;Basia;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px0 +rs.0.id.39;id.39;Basia;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.39.px1 +rs.0.id.4;id.4;ID4;INPUT;input.t.0;ok;;czujnik temp. Salon +rs.0.id.4;id.4;ID4;INPUT;input.t.1;ok;;czujnik temp. Biuro Wojtek +rs.0.id.4;id.4;ID4;INPUT;input.t.2;ok;;czujnik temp. Sypialnia +rs.0.id.4;id.4;ID4;INPUT;input.t.3;ok;;czujnik temp. Duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.do.0;ok;;siłownik rozdzielacz R2 - salon +rs.0.id.4;id.4;ID4;OUTPUT;output.do.1;ok;;siłownik rozdzielacz R2 - biuro Wojtek +rs.0.id.4;id.4;ID4;OUTPUT;output.do.2;ok;;siłownik rozdzielacz R2 - sypialnia +rs.0.id.4;id.4;ID4;OUTPUT;output.do.3;ok;;siłownik rozdzielacz R2 - duża łazienka +rs.0.id.4;id.4;ID4;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0 +rs.0.id.4;id.4;ID4;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.40;id.40;Biuro A;INPUT;input.t.0;ok;;Przycisk B1 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.1;ok;;Przycisk B2 +rs.0.id.40;id.40;Biuro A;INPUT;input.t.2;nc;;Wolne wejście +rs.0.id.40;id.40;Biuro A;INPUT;input.t.3;ok;;Przycisk B4 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.0;ok;;Oświetlenie B1 główne +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.1;ok;;Oświetlenie B2 nad biurkiem +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.2;ok;;Oświetlenie B3 biurko lampa +rs.0.id.40;id.40;Biuro A;OUTPUT;output.do.3;ok;;Oświetlenie B4 dla ledów +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px0 +rs.0.id.40;id.40;Biuro A;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.40.px1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.0;ok;;Przycisk W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.1;ok;;Przycisk W3 halogen prysznic +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.2;ok;;Przycisk P1 poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;INPUT;input.t.3;ok;;Przycisk P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.0;ok;;Oświetlenie W2 góra halogeny +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.1;ok;;Oświetlenie W3 halogen prysznic + led +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.2;ok;;Oświetlenie P1 Poddasze 1 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.do.3;ok;;Oświetlenie P2 Poddasze 2 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.41.px0 +rs.0.id.41;id.41;WC/Poddasze;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.0;ok;;czujnik temp. zasialnia kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.1;ok;;czujnik temp. w zbiorniku buforowym na dole +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.2;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;INPUT;input.t.3;ok;;brak czujnika +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.0;ok;;pompa obiegowa kominka +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.1;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.2;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.do.3;ok;; +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.10.px0 +rs.0.id.5;id.10;ID10 Sterownik kominka;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. +rs.0.id.6;id.6;ID6;INPUT;input.t.0;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.1;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.2;ok;; +rs.0.id.6;id.6;ID6;INPUT;input.t.3;ok;; +rs.0.id.6;id.6;ID6;OUTPUT;output.do.0;ok;;pompa głębinowa +rs.0.id.6;id.6;ID6;OUTPUT;output.do.1;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.2;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.do.3;ok;;elektro zawór zraszaczy sekcja X +rs.0.id.6;id.6;ID6;OUTPUT;output.px.0;nc;;Opcjonalne wyjście PWM/PX. Adres rs.0.id.6.px0 +rs.0.id.6;id.6;ID6;OUTPUT;output.px.1;nc;;Opcjonalne wyjście PWM/PX. diff --git a/proj-ib-lighting-rs485-zarki.yaml b/proj-ib-lighting-rs485-zarki.yaml index 3a47859..214118d 100644 --- a/proj-ib-lighting-rs485-zarki.yaml +++ b/proj-ib-lighting-rs485-zarki.yaml @@ -278,7 +278,7 @@ - io_id: "input.t.1" status: "ok" mapping: "" - description: """ + description: "" - io_id: "input.t.2" status: "ok" mapping: "" diff --git a/testowe/check_perm.sh b/testowe/check_perm.sh new file mode 100755 index 0000000..a9f141e --- /dev/null +++ b/testowe/check_perm.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +chown -R root:root /ibsystem +chmod 755 /ibsystem/*.sh +chmod 755 /ibsystem/ibvunit/ibvunit +chmod 755 /ibsystem/ibmanager/ibmanager +chmod 755 /ibsystem/ibls diff --git a/testowe/check_status.py b/testowe/check_status.py new file mode 100644 index 0000000..6457cef --- /dev/null +++ b/testowe/check_status.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., do.x + output_name = line.split('=')[0].strip() + output_name = output_name.split('.')[-2] + '.' + output_name.split('.')[-1] # do.x + print(f"Active output: {output_name}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status.sh b/testowe/check_status.sh new file mode 100755 index 0000000..f0aa2ba --- /dev/null +++ b/testowe/check_status.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +# Funkcja wyświetlająca pomoc +show_help() { + echo "Użycie: $0 [OPCJE]" + echo + echo "Opcje:" + echo " --show_active_output Wyświetl tylko sterowniki z aktywnymi wyjściami" + echo " --all Wyświetl pełne informacje o sterownikach" + echo " --help Wyświetl tę pomoc" + exit 1 +} + +# Jeśli nie podano żadnych argumentów, wyświetl pomoc +if [ $# -eq 0 ]; then + show_help +fi + +# Domyślne wartości parametrów +show_active_output=false # Domyślnie nie pokazujemy aktywnych wyjść +show_all=false # Domyślnie nie pokazujemy wszystkich informacji + +# Sprawdzenie, jakie parametry zostały podane +for arg in "$@"; do + case $arg in + --show_active_output) + show_active_output=true + shift + ;; + --all) + show_all=true + shift + ;; + --help) + show_help + shift + ;; + *) + echo "Nieznana opcja: $arg" + show_help + ;; + esac +done + +# Plik XML, z którego będziemy pobierać wartości Address +xml_file="ibvunit/ibvunit.xml" + +# Wyciągnięcie wartości Address tylko z sekcji +awk '//' "$xml_file" | grep -oP 'Address="\K\d+' | while read -r address; do + # Uruchomienie polecenia dla każdej wartości Address + output=$(./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.$address.out;);") + + # Jeśli parametr show_all jest ustawiony na 'true', pokaż pełne wyjście polecenia + if [ "$show_all" = true ]; then + echo "Sterownik id.$address:" + echo "$output" + fi + + # Jeśli parametr show_active_output jest ustawiony na 'true', wyświetl tylko sterowniki z włączonymi wyjściami + if [ "$show_active_output" = true ]; then + active_outputs=$(echo "$output" | grep -oP 'do\.\d+ = 1') + + if [ -n "$active_outputs" ]; then + echo "Sterownik id.$address ma aktywne wyjścia:" + echo "$active_outputs" | while read -r line; do + output_name=$(echo "$line" | cut -d' ' -f1) # wyciągnięcie nazwy wyjścia, np. do.0 + echo "Włączone wyjście: $output_name" + done + fi + fi +done + diff --git a/testowe/check_status1.py b/testowe/check_status1.py new file mode 100644 index 0000000..7ca8f94 --- /dev/null +++ b/testowe/check_status1.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 + +import sys +import subprocess +import xml.etree.ElementTree as ET + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +# Function to display help + +def show_help(): + print() + print("Options:") + print(" --show_active_output Display only controllers with active outputs") + print(" --all Display full information about controllers") + print(" --show-id Display outputs only from the specified controller") + print(" (Works only with --all or --show_active_output)") + print(" --all --show-id 35") + print(" --show_active_output--show-id 35") + print(" --help Display this help message") + sys.exit(1) + +# Function to run system commands and return the output +def run_command(command): + result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + return result.stdout.decode('utf-8') + +# Parse the XML file and get Address values from the section +def get_addresses_from_xml(xml_file): + tree = ET.parse(xml_file) + root = tree.getroot() + + # Namespace must be included for the XML + namespace = {'ns': 'http://www.insbud.net/ibvunit'} + + # Extract all addresses from the Devices section + addresses = [] + for device in root.findall('.//ns:Devices/ns:Device', namespace): + addresses.append(device.get('Address')) + + return addresses + +# Read dok.txt and create a mapping of output names to their descriptions +def load_output_descriptions(dok_file): + descriptions = {} + current_id = None + with open(dok_file, 'r') as file: + for line in file: + line = line.strip() + if line.startswith("id."): # New controller section + current_id = line.split(".")[1] + elif current_id is not None and line.startswith("output.do."): + output_name = f"rs.0.id.{current_id}.{line.split('=')[0].strip()}" + description = line.split('=')[1].strip() + descriptions[output_name] = description + return descriptions + +# Main logic +def main(): + show_active_output = False + show_all = False + specific_id = None + + # Check arguments + if len(sys.argv) == 1: + show_help() + + i = 1 + while i < len(sys.argv): + arg = sys.argv[i] + if arg == "--show_active_output": + show_active_output = True + elif arg == "--all": + show_all = True + elif arg == "--show-id": + if i + 1 < len(sys.argv): # Check if id is provided + specific_id = sys.argv[i + 1] + i += 1 # Skip to the next argument + else: + print("Error: You must provide an identifier after --show-id.") + show_help() + elif arg == "--help": + show_help() + else: + print(f"Unknown option: {arg}") + show_help() + i += 1 # Move to the next argument + + # Validate argument combinations + if specific_id is not None and not (show_active_output or show_all): + print("Error: --show-id works only with --all or --show_active_output.") + show_help() + + # Get addresses from the XML file + addresses = get_addresses_from_xml(xml_file) + + # Load output descriptions from dok.txt + output_descriptions = load_output_descriptions(dok_file) + + # For each address, execute the corresponding command + for address in addresses: + # Check if the identifier matches + if specific_id is not None and specific_id != address: + continue # Skip other identifiers + + output = run_command(f'./ibls -a 127.0.0.1 --pretty -p 2001 -c "get(rs.0.id.{address}.out;);"') + + # If --all option is provided, display full output without active output details + if show_all: + print(f"Controller id.{address}:") + print(output) + + # If --show_active_output option is provided, display only active outputs + if show_active_output: + active_outputs = [line for line in output.splitlines() if 'do.' in line and '= 1' in line] + + if active_outputs: + for line in active_outputs: + # Extract the full output name, e.g., rs.0.id.39.output.do.2 + output_name = line.split('=')[0].strip() + output_identifier = output_name.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier.split('.')[-1]}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier.split('.')[-1]}" # Corrected to just 'output.do.x' + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + print(f"Controller id.{address} output.{output_identifier.split('.')[-1]} name: {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/check_status2.py b/testowe/check_status2.py new file mode 100644 index 0000000..5556d58 --- /dev/null +++ b/testowe/check_status2.py @@ -0,0 +1,81 @@ +import argparse + +# Path to the XML file +xml_file = "ibvunit/ibvunit.xml" +dok_file = "dok.txt" + +def parse_arguments(): + parser = argparse.ArgumentParser(description="Controller output monitoring script.") + parser.add_argument('--all', action='store_true', help='Show all controller outputs.') + parser.add_argument('--show-active-output', action='store_true', help='Show only active outputs.') + parser.add_argument('--show-id', type=int, help='Show outputs for a specific controller ID.') + return parser.parse_args() + +def read_dok_file(dok_file): + output_descriptions = {} + controllers = {} + + with open(dok_file, 'r') as f: + lines = f.readlines() + current_id = None + for line in lines: + line = line.strip() + if line.startswith("id."): + current_id = line.split('.')[1] + controllers[current_id] = {'active_outputs': [], 'name': f'Controller {current_id}'} + elif current_id and "=" in line: + key, value = line.split("=") + output_key = key.strip() + output_descriptions[output_key] = value.strip() + # Check if the output key is an active output for the current controller + if output_key.startswith('output.do.'): + controllers[current_id]['active_outputs'].append(output_key) + + return output_descriptions, controllers + +def main(): + args = parse_arguments() + + # Read output descriptions from dok.txt and create controllers dictionary + output_descriptions, controllers = read_dok_file(dok_file) + + if not (args.all or args.show_active_output): + print("Error: You must provide either --all or --show-active-output.") + return + + for address, controller in controllers.items(): + if args.show_id is not None and int(address) != args.show_id: + continue + + if args.all: + print(f"{controller['name']}:") + for output in controller['active_outputs']: + description = output_descriptions.get(output, "Unknown output") + print(f"{output} name: {description}") + + if args.show_active_output: + active_outputs = controller['active_outputs'] + if active_outputs: + for line in active_outputs: + output_identifier = line.split('.')[-1] # This should give us do.x + + # Look for the description in the loaded mappings + full_output_name = f"rs.0.id.{address}.output.{output_identifier}" + description = output_descriptions.get(full_output_name, "Unknown output") + + # Debug: Print the full output name and the corresponding description key + print(f"Checking for output: {full_output_name} (Key: {output_identifier})") + + # Check if the output is present in the descriptions and get the name + output_description_key = f"output.do.{output_identifier}" + print(f"Checking for description with key: {output_description_key}") # Debug line + if output_description_key in output_descriptions: + description = output_descriptions[output_description_key] + + # Change output to include the full output key + print(f"Controller id.{address} output.do.{output_identifier} - {description}") + else: + print(f"Controller id.{address} has no active outputs.") + +if __name__ == "__main__": + main() diff --git a/testowe/desc_gen.py b/testowe/desc_gen.py new file mode 100644 index 0000000..95e1757 --- /dev/null +++ b/testowe/desc_gen.py @@ -0,0 +1,118 @@ +import re + +def load_device_list(file_path): + """Wczytuje listę urządzeń z pliku.""" + with open(file_path, 'r', encoding='utf-8') as file: + lines = [line.strip() for line in file if line.strip()] + return lines + +def parse_devices(lines): + """Grupuje urządzenia według ID, pomijając te, które już mają opis.""" + devices = {} + for line in lines: + if '-' in line: # Pomija urządzenia, które już mają opis + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id not in devices: + devices[device_id] = [] + devices[device_id].append(line) + return devices + +def load_existing_descriptions(file_path): + """Wczytuje istniejące opisy z pliku wynikowego.""" + try: + with open(file_path, 'r', encoding='utf-8') as file: + return {line.split(" - ")[0].strip(): line.strip() for line in file if " - " in line} + except FileNotFoundError: + return {} + +def generate_descriptions(devices, existing_descriptions): + """Interaktywnie generuje opisy dla urządzeń.""" + descriptions = {} + try: + for device_id, components in devices.items(): + print(f"\nID urządzenia: {device_id}") + # Generowanie opisu głównego urządzenia + if f"id {device_id}" in existing_descriptions: + current_desc = existing_descriptions[f"id {device_id}"] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input("Czy chcesz zmodyfikować ten opis? (tak/nie): ").strip().lower() + if modify == "nie": + continue + else: + description = input(f"Podaj nowy opis dla ID {device_id} (np. wiatrołap/kuchnia): ").strip() + if not description: + description = "brak" + descriptions[device_id] = {f"id {device_id}": description} + + # Generowanie opisów dla komponentów urządzenia + for component in components: + if component in existing_descriptions: + current_desc = existing_descriptions[component] + print(f"Obecny opis: {current_desc.split(' - ', 1)[1]}") + modify = input(f"Czy chcesz zmodyfikować opis dla {component}? (tak/nie): ").strip().lower() + if modify == "nie": + continue + component_desc = input(f"Podaj opis dla {component}: ").strip() + if not component_desc: + component_desc = "brak" + descriptions.setdefault(device_id, {})[component] = component_desc + + except (KeyboardInterrupt, EOFError): # Obsługuje Ctrl+C i Ctrl+Z + print("\nZatrzymano interakcję. Zapisywanie danych...") + return descriptions, True + + return descriptions, False + +def save_descriptions(file_path, descriptions, original_lines, existing_descriptions): + """Zapisuje opisy do pliku, zachowując istniejącą strukturę.""" + with open(file_path, 'w', encoding='utf-8') as file: + for line in original_lines: + if '-' in line: + file.write(line + '\n') + continue + if line in existing_descriptions: + file.write(existing_descriptions[line] + '\n') + continue + match = re.match(r'rs\.0\.id\.(\d+)', line) + if match: + device_id = match.group(1) + if device_id in descriptions and line in descriptions[device_id]: + file.write(f"{line} - {descriptions[device_id][line]}\n") + else: + file.write(line + '\n') + else: + file.write(line + '\n') + +def main(): + input_file = 'dok.txt' + output_file = 'dok_output.txt' + + print("Wczytywanie urządzeń i istniejących opisów...") + original_lines = load_device_list(input_file) + devices = parse_devices(original_lines) + existing_descriptions = load_existing_descriptions(output_file) + + if not devices: + print("Brak urządzeń do opisania.") + return + + print(f"Znaleziono {len(devices)} urządzeń do opisania.") + + all_descriptions = {} + while devices: + descriptions, should_exit = generate_descriptions(devices, existing_descriptions) + all_descriptions.update(descriptions) + if should_exit: + break + + print("\nZapisywanie opisów do pliku...") + save_descriptions(output_file, all_descriptions, original_lines, existing_descriptions) + print(f"Opisy zapisano w pliku {output_file}.") + print("Zakończono.") + +if __name__ == "__main__": + main() + diff --git a/testowe/dok.txt b/testowe/dok.txt new file mode 100644 index 0000000..8423487 --- /dev/null +++ b/testowe/dok.txt @@ -0,0 +1,239 @@ +id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +id 02 +rs.0.id.02.t.0 +rs.0.id.02.t.1 +rs.0.id.02.t.2 +rs.0.id.02.t.3 +rs.0.id.02.do.t.0 +rs.0.id.02.do.t.1 +rs.0.id.02.do.t.2 +rs.0.id.02.do.t.3 +rs.0.id.02.px0 +rs.0.id.02.px1 + +id 03 +rs.0.id.03.t.0 +rs.0.id.03.t.1 +rs.0.id.03.t.2 +rs.0.id.03.t.3 +rs.0.id.03.do.t.0 +rs.0.id.03.do.t.1 +rs.0.id.03.do.t.2 +rs.0.id.03.do.t.3 +rs.0.id.03.px0 +rs.0.id.03.px1 + +id 04 +rs.0.id.04.t.0 +rs.0.id.04.t.1 +rs.0.id.04.t.2 +rs.0.id.04.t.3 +rs.0.id.04.do.t.0 +rs.0.id.04.do.t.1 +rs.0.id.04.do.t.2 +rs.0.id.04.do.t.3 +rs.0.id.04.px0 +rs.0.id.04.px1 + +id 05 +rs.0.id.05.t.0 +rs.0.id.05.t.1 +rs.0.id.05.t.2 +rs.0.id.05.t.3 +rs.0.id.05.do.t.0 +rs.0.id.05.do.t.1 +rs.0.id.05.do.t.2 +rs.0.id.05.do.t.3 +rs.0.id.05.px0 +rs.0.id.05.px1 + +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oświetlenie H1 +rs.0.id.30.do.t.1 - Oświetlenie H2 +rs.0.id.30.do.t.2 - Oświetlenie K1, szynoprzewód +rs.0.id.30.do.t.3 - Oświetlenie K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak + +id 31 +rs.0.id.31.t.0 +rs.0.id.31.t.1 +rs.0.id.31.t.2 +rs.0.id.31.t.3 +rs.0.id.31.do.t.0 +rs.0.id.31.do.t.1 +rs.0.id.31.do.t.2 +rs.0.id.31.do.t.3 +rs.0.id.31.px0 +rs.0.id.31.px1 + +id 32 +rs.0.id.32.t.0 +rs.0.id.32.t.1 +rs.0.id.32.t.2 +rs.0.id.32.t.3 +rs.0.id.32.do.t.0 +rs.0.id.32.do.t.1 +rs.0.id.32.do.t.2 +rs.0.id.32.do.t.3 +rs.0.id.32.px0 +rs.0.id.32.px1 + +id 33 +rs.0.id.33.t.0 +rs.0.id.33.t.1 +rs.0.id.33.t.2 +rs.0.id.33.t.3 +rs.0.id.33.do.t.0 +rs.0.id.33.do.t.1 +rs.0.id.33.do.t.2 +rs.0.id.33.do.t.3 +rs.0.id.33.px0 +rs.0.id.33.px1 + +id 34 +rs.0.id.34.t.0 +rs.0.id.34.t.1 +rs.0.id.34.t.2 +rs.0.id.34.t.3 +rs.0.id.34.do.t.0 +rs.0.id.34.do.t.1 +rs.0.id.34.do.t.2 +rs.0.id.34.do.t.3 +rs.0.id.34.px0 +rs.0.id.34.px1 + +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 + +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 + +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 + +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 + +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 + +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 + +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 + +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 + +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 + +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/testowe/dok_back.txt b/testowe/dok_back.txt new file mode 100644 index 0000000..8ccd2ec --- /dev/null +++ b/testowe/dok_back.txt @@ -0,0 +1,258 @@ +id.39id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +px.0 = empty +px.1 = empty +output.do.0 = oświetlenie główne +output.do.1 = halogeny nad biurkiem +output.do.2 = chmurka +output.do.3 = kinkiet koło łóżka + +id 01 +rs.0.id.01.t.0 +rs.0.id.01.t.1 +rs.0.id.01.t.2 +rs.0.id.01.t.3 +rs.0.id.01.do.t.0 +rs.0.id.01.do.t.1 +rs.0.id.01.do.t.2 +rs.0.id.01.do.t.3 +rs.0.id.01.px0 +rs.0.id.01.px1 + +id 02 +rs.0.id.02.t.0 +rs.0.id.02.t.1 +rs.0.id.02.t.2 +rs.0.id.02.t.3 +rs.0.id.02.do.t.0 +rs.0.id.02.do.t.1 +rs.0.id.02.do.t.2 +rs.0.id.02.do.t.3 +rs.0.id.02.px0 +rs.0.id.02.px1 + +id 03 +rs.0.id.03.t.0 +rs.0.id.03.t.1 +rs.0.id.03.t.2 +rs.0.id.03.t.3 +rs.0.id.03.do.t.0 +rs.0.id.03.do.t.1 +rs.0.id.03.do.t.2 +rs.0.id.03.do.t.3 +rs.0.id.03.px0 +rs.0.id.03.px1 + +id 04 +rs.0.id.04.t.0 +rs.0.id.04.t.1 +rs.0.id.04.t.2 +rs.0.id.04.t.3 +rs.0.id.04.do.t.0 +rs.0.id.04.do.t.1 +rs.0.id.04.do.t.2 +rs.0.id.04.do.t.3 +rs.0.id.04.px0 +rs.0.id.04.px1 + +id 05 +rs.0.id.05.t.0 +rs.0.id.05.t.1 +rs.0.id.05.t.2 +rs.0.id.05.t.3 +rs.0.id.05.do.t.0 +rs.0.id.05.do.t.1 +rs.0.id.05.do.t.2 +rs.0.id.05.do.t.3 +rs.0.id.05.px0 +rs.0.id.05.px1 + +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oświetlenie H1 +rs.0.id.30.do.t.1 - Oświetlenie H2 +rs.0.id.30.do.t.2 - Oświetlenie K1, szynoprzewód +rs.0.id.30.do.t.3 - Oświetlenie K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak + +id 31 +rs.0.id.31.t.0 +rs.0.id.31.t.1 +rs.0.id.31.t.2 +rs.0.id.31.t.3 +rs.0.id.31.do.t.0 +rs.0.id.31.do.t.1 +rs.0.id.31.do.t.2 +rs.0.id.31.do.t.3 +rs.0.id.31.px0 +rs.0.id.31.px1 + +id 32 +rs.0.id.32.t.0 +rs.0.id.32.t.1 +rs.0.id.32.t.2 +rs.0.id.32.t.3 +rs.0.id.32.do.t.0 +rs.0.id.32.do.t.1 +rs.0.id.32.do.t.2 +rs.0.id.32.do.t.3 +rs.0.id.32.px0 +rs.0.id.32.px1 + +id 33 +rs.0.id.33.t.0 +rs.0.id.33.t.1 +rs.0.id.33.t.2 +rs.0.id.33.t.3 +rs.0.id.33.do.t.0 +rs.0.id.33.do.t.1 +rs.0.id.33.do.t.2 +rs.0.id.33.do.t.3 +rs.0.id.33.px0 +rs.0.id.33.px1 + +id 34 +rs.0.id.34.t.0 +rs.0.id.34.t.1 +rs.0.id.34.t.2 +rs.0.id.34.t.3 +rs.0.id.34.do.t.0 +rs.0.id.34.do.t.1 +rs.0.id.34.do.t.2 +rs.0.id.34.do.t.3 +rs.0.id.34.px0 +rs.0.id.34.px1 + +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 + +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 + +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 + +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 + +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 + +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 + +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 + +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 + +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 + +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/testowe/dok_output.txt b/testowe/dok_output.txt new file mode 100644 index 0000000..6c98aa8 --- /dev/null +++ b/testowe/dok_output.txt @@ -0,0 +1,220 @@ +id 01 +rs.0.id.01.t.0 - czujnik temperatury wymiennika na kominku +rs.0.id.01.t.1 - brak +rs.0.id.01.t.2 - brak +rs.0.id.01.t.3 - brak +rs.0.id.01.do.t.0 - pompa kominka +rs.0.id.01.do.t.1 - brak +rs.0.id.01.do.t.2 - brak +rs.0.id.01.do.t.3 - brak +rs.0.id.01.px0 - brak +rs.0.id.01.px1 - brak +id 02 +rs.0.id.02.t.0 - brak +rs.0.id.02.t.1 - brak +rs.0.id.02.t.2 - brak +rs.0.id.02.t.3 - brak +rs.0.id.02.do.t.0 - brak +rs.0.id.02.do.t.1 - brak +rs.0.id.02.do.t.2 - brak +rs.0.id.02.do.t.3 - brak +rs.0.id.02.px0 - brak +rs.0.id.02.px1 - brak +id 03 +rs.0.id.03.t.0 - brak +rs.0.id.03.t.1 - brak +rs.0.id.03.t.2 - brak +rs.0.id.03.t.3 - brak +rs.0.id.03.do.t.0 - brak +rs.0.id.03.do.t.1 - brak +rs.0.id.03.do.t.2 - brak +rs.0.id.03.do.t.3 - brak +rs.0.id.03.px0 - brak +rs.0.id.03.px1 - brak +id 04 +rs.0.id.04.t.0 - brak +rs.0.id.04.t.1 - brak +rs.0.id.04.t.2 - brak +rs.0.id.04.t.3 - brak +rs.0.id.04.do.t.0 - brak +rs.0.id.04.do.t.1 - brak +rs.0.id.04.do.t.2 - brak +rs.0.id.04.do.t.3 - brak +rs.0.id.04.px0 - brak +rs.0.id.04.px1 - brak +id 05 +rs.0.id.05.t.0 - brak +rs.0.id.05.t.1 - brak +rs.0.id.05.t.2 - brak +rs.0.id.05.t.3 - brak +rs.0.id.05.do.t.0 - brak +rs.0.id.05.do.t.1 - brak +rs.0.id.05.do.t.2 - brak +rs.0.id.05.do.t.3 - brak +rs.0.id.05.px0 - brak +rs.0.id.05.px1 - brak +id 30 - wiatrołap/kuchnia +rs.0.id.30.t.0 - H1 przycisk, zug 2, Oświetlenie górne +rs.0.id.30.t.1 - H2 przycisk, zug 1, Led za siedziskiem +rs.0.id.30.t.2 - K1 przycisk, zug 3, +rs.0.id.30.t.3 - K2 przycisk, zug 4, +rs.0.id.30.do.t.0 - Oś H1 +rs.0.id.30.do.t.1 - Oś H2 +rs.0.id.30.do.t.2 - Oś K1, szynoprzewód +rs.0.id.30.do.t.3 - Oś K2, szynoprzewód +rs.0.id.30.px0 - brak +rs.0.id.30.px1 - brak +id 31 +rs.0.id.31.t.0 - przycisk K3, zug 5 +rs.0.id.31.t.1 - przycisk K4, zug 7 +rs.0.id.31.t.2 - przycisk K5 +rs.0.id.31.t.3 - przycisk K6 +rs.0.id.31.do.t.0 - Oś K3, halogeny okno +rs.0.id.31.do.t.1 - Oś K4, lampy nad barem +rs.0.id.31.do.t.2 - Oś K5, ledy pod półkami +rs.0.id.31.do.t.3 - Os K6, led okno +rs.0.id.31.px0 - brak +rs.0.id.31.px1 - brak +id 32 +rs.0.id.32.t.0 - przycisk J1, zug 14, J1 czarny +rs.0.id.32.t.1 - przycisk J2, zug 14,J2 brazowy +rs.0.id.32.t.2 - przycisk S1, zug 10, S1 czarny +rs.0.id.32.t.3 - przycisk S5, zug 10, S5 brazowy +rs.0.id.32.do.t.0 - Oś J1, Nad stołem +rs.0.id.32.do.t.1 - Oś J2, Nad stołem # połączone razem J1 i J2 +rs.0.id.32.do.t.2 - Oś S1, Ring salon +rs.0.id.32.do.t.3 - oś S5, led dekoracyjny koło kanapy +rs.0.id.32.px0 - brak +rs.0.id.32.px1 - brak +id 33 +rs.0.id.33.t.0 - przycisk S2, zug 11 +rs.0.id.33.t.1 - przycisk S3, zug 11 +rs.0.id.33.t.2 - przycisk S4 +rs.0.id.33.t.3 - przycisk S6 +rs.0.id.33.do.t.0 - Oś S2, spotlight za kanapom +rs.0.id.33.do.t.1 - Oś S3, spotlight przed TV +rs.0.id.33.do.t.2 - Oś S4, Led TV +rs.0.id.33.do.t.3 - Oś S6, Led sufit wnęka, przewód 4.4, zug 13 +rs.0.id.33.px0 - brak +rs.0.id.33.px1 - brak +id 34 +rs.0.id.34.t.0 - przycisk H3, zug 16, szyno przewód +rs.0.id.34.t.1 - przycisk H4, zug 16, szyno przewód +rs.0.id.34.t.2 - przycisk H5 +rs.0.id.34.t.3 - przycisk H6 +rs.0.id.34.do.t.0 - Oś H3, szyno przewód +rs.0.id.34.do.t.1 - Oś H4, szyno przewód +rs.0.id.34.do.t.2 - Oś H5, zug 17, przedów 5.2 Ledy pionowe +rs.0.id.34.do.t.3 - Oś H6, zug 18, przewód 5.3 Led kominek #Brazowy 230v gniazdo kominek, niebieski N, Żółty 230V zasilacz Led kominek +rs.0.id.34.px0 - brak +rs.0.id.34.px1 - brak +id 35 +rs.0.id.35.t.0 +rs.0.id.35.t.1 +rs.0.id.35.t.2 +rs.0.id.35.t.3 +rs.0.id.35.do.t.0 +rs.0.id.35.do.t.1 +rs.0.id.35.do.t.2 +rs.0.id.35.do.t.3 +rs.0.id.35.px0 +rs.0.id.35.px1 +id 36 +rs.0.id.36.t.0 +rs.0.id.36.t.1 +rs.0.id.36.t.2 +rs.0.id.36.t.3 +rs.0.id.36.do.t.0 +rs.0.id.36.do.t.1 +rs.0.id.36.do.t.2 +rs.0.id.36.do.t.3 +rs.0.id.36.px0 +rs.0.id.36.px1 +id 37 +rs.0.id.37.t.0 +rs.0.id.37.t.1 +rs.0.id.37.t.2 +rs.0.id.37.t.3 +rs.0.id.37.do.t.0 +rs.0.id.37.do.t.1 +rs.0.id.37.do.t.2 +rs.0.id.37.do.t.3 +rs.0.id.37.px0 +rs.0.id.37.px1 +id 38 +rs.0.id.38.t.0 +rs.0.id.38.t.1 +rs.0.id.38.t.2 +rs.0.id.38.t.3 +rs.0.id.38.do.t.0 +rs.0.id.38.do.t.1 +rs.0.id.38.do.t.2 +rs.0.id.38.do.t.3 +rs.0.id.38.px0 +rs.0.id.38.px1 +id 39 +rs.0.id.39.t.0 +rs.0.id.39.t.1 +rs.0.id.39.t.2 +rs.0.id.39.t.3 +rs.0.id.39.do.t.0 +rs.0.id.39.do.t.1 +rs.0.id.39.do.t.2 +rs.0.id.39.do.t.3 +rs.0.id.39.px0 +rs.0.id.39.px1 +id 40 +rs.0.id.40.t.0 +rs.0.id.40.t.1 +rs.0.id.40.t.2 +rs.0.id.40.t.3 +rs.0.id.40.do.t.0 +rs.0.id.40.do.t.1 +rs.0.id.40.do.t.2 +rs.0.id.40.do.t.3 +rs.0.id.40.px0 +rs.0.id.40.px1 +id 41 +rs.0.id.41.t.0 +rs.0.id.41.t.1 +rs.0.id.41.t.2 +rs.0.id.41.t.3 +rs.0.id.41.do.t.0 +rs.0.id.41.do.t.1 +rs.0.id.41.do.t.2 +rs.0.id.41.do.t.3 +rs.0.id.41.px0 +rs.0.id.41.px1 +id 42 +rs.0.id.42.t.0 +rs.0.id.42.t.1 +rs.0.id.42.t.2 +rs.0.id.42.t.3 +rs.0.id.42.do.t.0 +rs.0.id.42.do.t.1 +rs.0.id.42.do.t.2 +rs.0.id.42.do.t.3 +rs.0.id.42.px0 +rs.0.id.42.px1 +id 43 +rs.0.id.43.t.0 +rs.0.id.43.t.1 +rs.0.id.43.t.2 +rs.0.id.43.t.3 +rs.0.id.43.do.t.0 +rs.0.id.43.do.t.1 +rs.0.id.43.do.t.2 +rs.0.id.43.do.t.3 +rs.0.id.43.px0 +rs.0.id.43.px1 +id xx +rs.0.id.xx.t.0 +rs.0.id.xx.t.1 +rs.0.id.xx.t.2 +rs.0.id.xx.t.3 +rs.0.id.xx.do.t.0 +rs.0.id.xx.do.t.1 +rs.0.id.xx.do.t.2 +rs.0.id.xx.do.t.3 +rs.0.id.xx.px0 +rs.0.id.xx.px1 diff --git a/testowe/test1.sh b/testowe/test1.sh new file mode 100755 index 0000000..570a98a --- /dev/null +++ b/testowe/test1.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Funkcja dodająca komendy do crontaba +disable_light_cronjob() { + (crontab -l 2>/dev/null; echo "25 2 * * * /ibsystem/ibls -a 127.0.0.1 --pretty -p 2001 -c 'set(rs.0.id.35.setting.light.1=1;);'") | crontab - + (crontab -l 2>/dev/null; echo "26 2 * * * /ibsystem/ibls -a 127.0.0.1 --pretty -p 2001 -c 'set(rs.0.id.35.setting.light.1=0;);'") | crontab - +} + +# Wywołanie funkcji +disable_light_cronjob + diff --git a/wydruk_id2-5.html b/wydruk_id2-5.html new file mode 100644 index 0000000..40fe037 --- /dev/null +++ b/wydruk_id2-5.html @@ -0,0 +1,223 @@ + + + +Sterowniki ID2-ID5 + + +

STEROWNIKI ID2-ID5 - DO EDYCJI (wydrukuj i uzupełnij)

+
===========================================
+ STEROWNIKI ID2-ID5 - DO EDYCJI
+ Data wydruku: $(date)
+===========================================
+
+      - device_id: "rs.0.id.2"
+        model_id: "IB-CTRL-IO-RS485"
+        location: "ID2 Sterownik ogrzewania podłogowego"
+        description: |
+          Sterownik ID2 Sterownik ogrzewania podłogowego.
+        connections:
+          - bus_id: "rs.0"
+            address: "id.2"
+        io:
+          - io_id: "input.t.0"
+            status: "ok"
+            mapping: ""
+            description: "XXX"
+          - io_id: "input.t.1"
+            status: "ok"
+            mapping: ""
+            description: "XXX"
+          - io_id: "input.t.2"
+            status: "ok"
+            mapping: ""
+            description: "XXX"
+          - io_id: "input.t.3"
+            status: "ok"
+            mapping: ""
+            description: "XXX"
+          - io_id: "output.do.0"
+            status: "ok"
+            mapping: ""
+            description: "zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu)"
+          - io_id: "output.do.1"
+            status: "ok"
+            mapping: ""
+            description: "zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor]"
+          - io_id: "output.do.2"
+            status: "ok"
+            mapping: ""
+            description: "zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu)"
+          - io_id: "output.do.3"
+            status: "ok"
+            mapping: ""
+            description: "zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor]"
+          - io_id: "output.px.0"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0"
+          - io_id: "output.px.1"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX."
+        extension_modules: []
+      # Strefa 3: starownik ID3 przenieść czujniki z ID5
+      - device_id: "rs.0.id.3"
+        model_id: "IB-CTRL-IO-RS485"
+        location: "ID3"
+        description: |
+          Sterownik ID3 syterownik ogrzewania podłogowego.
+        connections:
+          - bus_id: "rs.0"
+            address: "id.3"
+        io:
+          - io_id: "input.t.0"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Basia" #do przeniesienia z ID5
+          - io_id: "input.t.1"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Ania" #do przeniesienia z ID5
+          - io_id: "input.t.2"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. WC" #do przeniesienia z ID5
+          - io_id: "input.t.3"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Wiatrołap" #do przeniesienia z ID5
+          - io_id: "output.do.0"
+            status: "ok"
+            mapping: ""
+            description: "siłownik rozdzielacz R1 - Basia"
+          - io_id: "output.do.1"
+            status: "ok"
+            mapping: ""
+            description: "siłownik rozdzielacz R1 - Ania"
+          - io_id: "output.do.2"
+            status: "ok"
+            mapping: ""
+            description: "siłownik pokoju - WC"
+          - io_id: "output.do.3"
+            status: "ok"
+            mapping: ""
+            description: "siłownik pokoju - Wiatrołap"
+          - io_id: "output.px.0"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0"
+          - io_id: "output.px.1"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX."
+        extension_modules: []
+
+      # Strefa 4: starownik ID4 do przeniesienie sterowanie nawadnianiem do ID6
+      - device_id: "rs.0.id.4"
+        model_id: "IB-CTRL-IO-RS485"
+        location: "ID4"
+        description: |
+          Sterownik ID4 ogrzewania podłogowego.
+        connections:
+          - bus_id: "rs.0"
+            address: "id.4"
+        io:
+          - io_id: "input.t.0"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Salon"
+          - io_id: "input.t.1"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Biuro Wojtek"
+          - io_id: "input.t.2"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Sypialnia"
+          - io_id: "input.t.3"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Duża łazienka"
+          - io_id: "output.do.0"
+            status: "ok"
+            mapping: ""
+            description: "siłownik rozdzielacz R2 - salon" #obecnie jest "pompa głębinowa"
+          - io_id: "output.do.1"
+            status: "ok"
+            mapping: ""
+            description: "siłownik rozdzielacz R2 - biuro Wojtek" #obecnie jest "elektro zawór zraszaczy sekcja X`"
+          - io_id: "output.do.2"
+            status: "ok"
+            mapping: ""
+            description: "siłownik rozdzielacz R2 - sypialnia" # obecnie jest "elektro zawór zraszaczy sekcja X"
+          - io_id: "output.do.3"
+            status: "ok"
+            mapping: ""
+            description: "siłownik rozdzielacz R2 - duża łazienka" # obecnie jest "elektro zawór zraszaczy sekcja X"
+          - io_id: "output.px.0"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0"
+          - io_id: "output.px.1"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX."
+        extension_modules: []
+      # Strefa 5: starownik ID5
+      - device_id: "rs.0.id.5"
+        model_id: "IB-CTRL-IO-RS485"
+        location: "ID5"
+        description: |
+          Sterownik ID5 do sterowania nawadnianiem.
+        connections:
+          - bus_id: "rs.0"
+            address: "id.5"
+        io:
+          - io_id: "input.t.0"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Basia" #do przeniesienia do ID3
+          - io_id: "input.t.1"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Biuro Ania" #do przeniesienia do ID3
+          - io_id: "input.t.2"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. WC" #do przeniesienia do ID3
+          - io_id: "input.t.3"
+            status: "ok"
+            mapping: ""
+            description: "czujnik temp. Wiatrołap" #do przeniesienia do ID3
+          - io_id: "output.do.0"
+            status: "ok"
+            mapping: ""
+            description: "elektro zawór zraszaczy sekcja X"
+          - io_id: "output.do.1"
+            status: "ok"
+            mapping: ""
+            description: "elektro zawór zraszaczy sekcja X"
+          - io_id: "output.do.2"
+            status: "ok"
+            mapping: ""
+            description: "elektro zawór zraszaczy sekcja X"
+          - io_id: "output.do.3"
+            status: "ok"
+            mapping: ""
+            description: "elektro zawór zraszaczy sekcja X"
+          - io_id: "output.px.0"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX. Adres rs.0.id.5.px0"
+          - io_id: "output.px.1"
+            status: "nc"
+            mapping: ""
+            description: "Opcjonalne wyjście PWM/PX."
+        extension_modules: []
+      # Strefa 6: starownik ID6 przenieść tu wszystko z ID4 - sterowanie nawadnianiem -- dołożyć sterownik
+      - device_id: "rs.0.id.6"
+
\ No newline at end of file diff --git a/wydruk_id2-5.txt b/wydruk_id2-5.txt new file mode 100644 index 0000000..3870ef4 --- /dev/null +++ b/wydruk_id2-5.txt @@ -0,0 +1,211 @@ +=========================================== + STEROWNIKI ID2-ID5 - DO EDYCJI + Data wydruku: $(date) +=========================================== + + - device_id: "rs.0.id.2" + model_id: "IB-CTRL-IO-RS485" + location: "ID2 Sterownik ogrzewania podłogowego" + description: | + Sterownik ID2 Sterownik ogrzewania podłogowego. + connections: + - bus_id: "rs.0" + address: "id.2" + io: + - io_id: "input.t.0" + status: "ok" + mapping: "" + description: "XXX" + - io_id: "input.t.1" + status: "ok" + mapping: "" + description: "XXX" + - io_id: "input.t.2" + status: "ok" + mapping: "" + description: "XXX" + - io_id: "input.t.3" + status: "ok" + mapping: "" + description: "XXX" + - io_id: "output.do.0" + status: "ok" + mapping: "" + description: "zawór mieszający Rozdzielacz R1-p.tech (zimnej, dobór z powrotu)" + - io_id: "output.do.1" + status: "ok" + mapping: "" + description: "zawór mieszający Rozdzielacz R1-p.tech (ciepłej, dobór z zasilania[bufor]" + - io_id: "output.do.2" + status: "ok" + mapping: "" + description: "zawór mieszający Rozdzielacz R2-salon (zimnej, dobór z powrotu)" + - io_id: "output.do.3" + status: "ok" + mapping: "" + description: "zawór mieszający Rozdzielacz R2-salon (ciepłej, dobór z zasilania[bufor]" + - io_id: "output.px.0" + status: "nc" + mapping: "" + description: "Opcjonalne wyjście PWM/PX. Adres rs.0.id.2.px0" + - io_id: "output.px.1" + status: "nc" + mapping: "" + description: "Opcjonalne wyjście PWM/PX." + extension_modules: [] + # Strefa 3: starownik ID3 przenieść czujniki z ID5 + - device_id: "rs.0.id.3" + model_id: "IB-CTRL-IO-RS485" + location: "ID3" + description: | + Sterownik ID3 syterownik ogrzewania podłogowego. + connections: + - bus_id: "rs.0" + address: "id.3" + io: + - io_id: "input.t.0" + status: "ok" + mapping: "" + description: "czujnik temp. Basia" #do przeniesienia z ID5 + - io_id: "input.t.1" + status: "ok" + mapping: "" + description: "czujnik temp. Ania" #do przeniesienia z ID5 + - io_id: "input.t.2" + status: "ok" + mapping: "" + description: "czujnik temp. WC" #do przeniesienia z ID5 + - io_id: "input.t.3" + status: "ok" + mapping: "" + description: "czujnik temp. Wiatrołap" #do przeniesienia z ID5 + - io_id: "output.do.0" + status: "ok" + mapping: "" + description: "siłownik rozdzielacz R1 - Basia" + - io_id: "output.do.1" + status: "ok" + mapping: "" + description: "siłownik rozdzielacz R1 - Ania" + - io_id: "output.do.2" + status: "ok" + mapping: "" + description: "siłownik pokoju - WC" + - io_id: "output.do.3" + status: "ok" + mapping: "" + description: "siłownik pokoju - Wiatrołap" + - io_id: "output.px.0" + status: "nc" + mapping: "" + description: "Opcjonalne wyjście PWM/PX. Adres rs.0.id.3.px0" + - io_id: "output.px.1" + status: "nc" + mapping: "" + description: "Opcjonalne wyjście PWM/PX." + extension_modules: [] + + # Strefa 4: starownik ID4 do przeniesienie sterowanie nawadnianiem do ID6 + - device_id: "rs.0.id.4" + model_id: "IB-CTRL-IO-RS485" + location: "ID4" + description: | + Sterownik ID4 ogrzewania podłogowego. + connections: + - bus_id: "rs.0" + address: "id.4" + io: + - io_id: "input.t.0" + status: "ok" + mapping: "" + description: "czujnik temp. Salon" + - io_id: "input.t.1" + status: "ok" + mapping: "" + description: "czujnik temp. Biuro Wojtek" + - io_id: "input.t.2" + status: "ok" + mapping: "" + description: "czujnik temp. Sypialnia" + - io_id: "input.t.3" + status: "ok" + mapping: "" + description: "czujnik temp. Duża łazienka" + - io_id: "output.do.0" + status: "ok" + mapping: "" + description: "siłownik rozdzielacz R2 - salon" #obecnie jest "pompa głębinowa" + - io_id: "output.do.1" + status: "ok" + mapping: "" + description: "siłownik rozdzielacz R2 - biuro Wojtek" #obecnie jest "elektro zawór zraszaczy sekcja X`" + - io_id: "output.do.2" + status: "ok" + mapping: "" + description: "siłownik rozdzielacz R2 - sypialnia" # obecnie jest "elektro zawór zraszaczy sekcja X" + - io_id: "output.do.3" + status: "ok" + mapping: "" + description: "siłownik rozdzielacz R2 - duża łazienka" # obecnie jest "elektro zawór zraszaczy sekcja X" + - io_id: "output.px.0" + status: "nc" + mapping: "" + description: "Opcjonalne wyjście PWM/PX. Adres rs.0.id.4.px0" + - io_id: "output.px.1" + status: "nc" + mapping: "" + description: "Opcjonalne wyjście PWM/PX." + extension_modules: [] + # Strefa 5: starownik ID5 + - device_id: "rs.0.id.5" + model_id: "IB-CTRL-IO-RS485" + location: "ID5" + description: | + Sterownik ID5 do sterowania nawadnianiem. + connections: + - bus_id: "rs.0" + address: "id.5" + io: + - io_id: "input.t.0" + status: "ok" + mapping: "" + description: "czujnik temp. Basia" #do przeniesienia do ID3 + - io_id: "input.t.1" + status: "ok" + mapping: "" + description: "czujnik temp. Biuro Ania" #do przeniesienia do ID3 + - io_id: "input.t.2" + status: "ok" + mapping: "" + description: "czujnik temp. WC" #do przeniesienia do ID3 + - io_id: "input.t.3" + status: "ok" + mapping: "" + description: "czujnik temp. Wiatrołap" #do przeniesienia do ID3 + - io_id: "output.do.0" + status: "ok" + mapping: "" + description: "elektro zawór zraszaczy sekcja X" + - io_id: "output.do.1" + status: "ok" + mapping: "" + description: "elektro zawór zraszaczy sekcja X" + - io_id: "output.do.2" + status: "ok" + mapping: "" + description: "elektro zawór zraszaczy sekcja X" + - io_id: "output.do.3" + status: "ok" + mapping: "" + description: "elektro zawór zraszaczy sekcja X" + - io_id: "output.px.0" + status: "nc" + mapping: "" + description: "Opcjonalne wyjście PWM/PX. Adres rs.0.id.5.px0" + - io_id: "output.px.1" + status: "nc" + mapping: "" + description: "Opcjonalne wyjście PWM/PX." + extension_modules: [] + # Strefa 6: starownik ID6 przenieść tu wszystko z ID4 - sterowanie nawadnianiem -- dołożyć sterownik + - device_id: "rs.0.id.6"