---
title: "Resi DALI"
description: "Stmívejte 64 DALI gear-ů a 16 skupin přes Modbus RTU na bráně RESI-DALI-SIO/ETH. TapHome runtime šablona s per-gear a skupinovým ovládáním."
url: "https://taphome.com/cs/compatibility/resi-dali-dali/"
language: cs
lastmod: 2026-11-15
generator: hugo
ai:
  topics: ["modbus-rtu","lighting","dali","dali-1.0","rs485","din-rail","gateway","dimming","broadcast"]
  questions: ["Jak stmívám jednotlivá DALI svítidla z TapHome přes bránu RESI-DALI-SIO?","Jak ovládám DALI skupiny přes runtime šablonu Resi DALI?","Jaký je rozdíl mezi šablonami Resi DALI a Resi Dali - Konfigurace?","Jak TapHome detekuje poruchu lampy a poruchu napájení na DALI gear-u?","Jak přidám nebo odeberu DALI gear ze skupiny z TapHome?","Jak zapojím RESI-DALI-SIO k napájecímu zdroji RESI-DALI-PS a DALI sběrnici?"]
---

# Resi DALI

Komunikace: Modbus RTU

- [Stránka produktu RESI-DALI-SIO/ETH/PS](https://www.resi.cc/prestashop/en/home/1-resi-dali-sioethps.html)
- [RESI Informatik & Automation](https://www.resi.cc)

## Návod na integraci

Šablona **Resi DALI** je runtime provozní protějšek nástroje *Resi Dali - Konfigurace* na uvedení do provozu. Připojuje TapHome k plně adresované DALI světelné sběrnici přes bránu RESI-DALI-SIO nebo RESI-DALI-ETH (Modbus-DALI) a zpřístupňuje denní řízení pro **až 64 individuálně adresovaných DALI ovládacích zařízení (gears)** (krátké adresy 0–63) a **16 DALI broadcast skupin** (0–15), plus per-gear DALI stav, diagnostiku poruch ovládacího zařízení a poruch lampy.

Komunikace s bránou používá Modbus RTU při 9600 baud 8N1. Zápisy jasu jdou do `H:510 LAMP LEVEL` (per-gear) a `H:520 GROUP LEVEL` (per-skupinu); per-gear konfigurační příkazy a dotazy jsou tunelovány přes `H:511 LAMP COMMAND` / `H:512 LAMP COMMAND + REPEAT`, přičemž registr brány `H:550 DALI STATUS` se polluje kvůli připravenosti odpovědi.

> [!NOTE]
> Tato šablona předpokládá, že **DALI krátké adresy jsou již naprogramovány** na sběrnici. Pokud gear-y ještě nemají adresu, použijte nejprve šablonu **Resi Dali - Konfigurace** (nebo bezplatný nástroj výrobce MODBUSConfigurator / DCA) ke spuštění průvodce náhodným adresováním DALI 2.0 — viz [*Vztah ke konfigurační šabloně*](https://taphome.com/cs/compatibility/resi-dali-dali/#vztah-ke-konfigurační-šabloně) níže.

## Hardwarové připojení

RESI-DALI-SIO (RS-485) a RESI-DALI-ETH (Ethernet) jsou master brány na DIN lištu, které sedí mezi sériovým/Ethernet hostem a DALI světelnou sběrnicí. SIO je v pouzdře CEM17 (17,5 × 90 × 56,4 mm) a ETH v širším pouzdře CEM35 (35,8 × 90 × 56,4 mm), aby se vešel RJ45 konektor. Žádná z bran nenapájí DALI sběrnici sama — průvodní DALI bus napájecí zdroj (RESI-DALI-PS nebo libovolný kompatibilní 200 mA DALI PSU) je povinný.

### Zapojení RESI-DALI-SIO (RS-485)

![Schéma zapojení RESI-DALI-SIO — externí DALI PSU (nahoře) a kombinace s RESI-DALI-PS (dole)](https://taphome.com/images/compatibility/resi-dali-dali/wiring-sio_hu_1af043ee91b2b0ed.jpg)

Svorky na levé straně RESI-DALI-SIO (shora → dolů): `GND`, `+12..48V=`, `RS485 DATA+ (A+)`, `RS485 DATA- (B-)`, `RS485 GND`, `RS232 TX`, `RS232 RX`, `RS232 GND`. Svorky DALI sběrnice na opačné straně jsou **`D+ / N/C / D-`** (3-pinový USLIM blok, prostřední `N/C` pin zůstává nezapojený).

Pro TapHome instalaci použijte rozhraní RS-485:

- `RS485 DATA+ (A+)` → A+/D+ na TapHome RS-485 sběrnici
- `RS485 DATA- (B-)` → B-/D- na TapHome RS-485 sběrnici
- `RS485 GND` → GND na TapHome napájecím zdroji (doporučeno pro stabilní komunikaci)
- `+12..48V=` / `GND` → 12–48 V DC primární napájení

### Zapojení RESI-DALI-ETH (Ethernet)

![Schéma zapojení RESI-DALI-ETH — externí DALI PSU (nahoře) a kombinace s RESI-DALI-PS (dole)](https://taphome.com/images/compatibility/resi-dali-dali/wiring-eth_hu_4bf0a5e8d8724d0b.jpg)

Ethernetová varianta má stejné svorky DALI sběrnice (`D+ / N/C / D-`) a vstupy primárního napájení (`GND`, `+12..48V=`), plus jediný RJ45 konektor pro 10/100 Mbit Ethernet. Tovární IP nastavení jsou **192.168.0.191 / 255.255.255.0 / 192.168.0.1** s Modbus Unit ID 255; vestavěné webové UI používá přihlašovací údaje `RESI` / `RESI`.

Protože jde o Modbus RTU šablonu, TapHome nekomunikuje s RESI-DALI-ETH přes nativní Modbus/TCP. Použijte ho raději v **transparentním režimu RTU-over-Ethernet**, nebo umístěte SIO za sériově-IP most (Moxa NPort, USR-TCP232) — viz *Konfigurace → Nastavení RTU-over-TCP* níže.

### DALI bus napájecí zdroj (RESI-DALI-PS)

![RESI-DALI-PS — napájení DALI sběrnice samostatně (nahoře) a kombinace se SIO/ETH bránou (dole)](https://taphome.com/images/compatibility/resi-dali-dali/wiring-dali-ps_hu_bea720a419338afa.jpg)

RESI-DALI-PS dodává až **200 mA** na DALI sběrnici (zkratový proud ~225 mA, napětí sběrnice typicky 14–18 V) a podporuje až 64 DALI 1.0 předřadníků nebo DALI 2.0 ovládacích zařízení na jedné lince. Primární strana akceptuje stejné 12–48 V DC napájení jako jednotka SIO/ETH. Brána a PSU se připojují na stejný pár `D+` / `D-` — PSU napájí sběrnici, zatímco brána čte a zapisuje DALI rámce.

Tři LED diody na PSU pomáhají při diagnostice poruch: **POWER** (primární 12–48 V OK, během normálního provozu vždy svítí), **DALI** (krátce bliká při DALI komunikaci), **ERR** (trvale svítí při poruše PSU, DALI zkratu nebo přetížení sběrnice — během normálního provozu musí být zhasnutá).

### Topologie DALI sběrnice

DALI linka má několik tvrdých omezení, která přímo ovlivňují stabilitu provozu:

| Průřez vodiče | Max délka DALI kabelu |
|--------------|----------------------|
| 1,5 mm² | 300 m |
| 1,0 mm² | 238 m |
| 0,75 mm² | 174 m |
| 0,5 mm² | 116 m |

Limit vychází z maximálně povoleného **úbytku napětí 2 V** na DALI kabelu. Další pravidla:

- Maximálně 64 DALI 1.0 předřadníků **a** až 64 DALI 2.0 ovládacích zařízení na sběrnici (oddělené prostory krátkých adres).
- Pouze stromová topologie — žádné kruhy, žádné smyčky.
- Skutečný počet gear-ů závisí také na jmenovitém proudu PSU (typicky 200 mA na RESI-DALI-PS; počítejte ~2 mA na gear plus rezervu).

> [!WARNING]
> **RESI-DALI-PS (nebo ekvivalentní DALI PSU) je povinný.** Bez něj brána nemůže napájet sběrnici a každé per-gear čtení skončí timeoutem *"Gear not responding!"*. Pokud se na dlouhou linku přidá druhý PSU, vložte DALI tlumivku nebo rozdělte sběrnici na galvanicky oddělené segmenty.

## Konfigurace

### Aktivace Modbus komunikace

Sériové parametry hosta na RESI-DALI-SIO se volí 4-polohovým DIP přepínačem na modulu. TapHome šablona je fixně nastavena na **9600 baud 8N1**, takže DIP přepínače musí odpovídat.

| DIP1 | DIP2 | Baud rate |
|------|------|-----------|
| **OFF** | **OFF** | **9600 bd (vyžadováno TapHome)** |
| ON | OFF | 19200 bd |
| OFF | ON | 38400 bd |
| ON | ON | Použije baud rate z FLASH (tovární default 57600 bd) |

| DIP4 | Zdroj Modbus Unit ID |
|------|---------------------|
| **OFF** | FLASH registr `H:65221` je akceptován — vyžadováno, pokud byla během uvedení do provozu naprogramována nestandardní Slave ID |
| ON | Hardwarový fallback — Unit ID je vynuceně `255`, FLASH hodnota je ignorována |

`DIP3` je pro produkt vyhrazený rezervní bit; nechejte ho v tovární poloze. Parita je fixní na `None` a stop bit na 1 (formát rámce 8N1) pro kombinace DIP1/DIP2 baud rate vybrané výše.

**RS-485 zakončení:** ukončete sběrnici odporem 120 Ω na obou koncích. TapHome Core poskytuje jedno zakončení na svých BUS svorkách; pokud je RESI brána posledním zařízením na lince, přidejte diskrétní 120 Ω rezistor mezi `A+` / `B-` na jejích RS-485 svorkách.

### Slave ID

Tovární předvolená Modbus Unit ID je **255** (FLASH registr `H:65221` čte `0xFFFF`, což brána klampuje na 255). Šablona zpřístupňuje servisní atribut na úrovni modulu **Slave ID**, který zpětně čte tento registr, takže nakonfigurovanou adresu lze ověřit po importu.

Změna Slave ID je záležitost uvedení do provozu řešená sesterskou šablonou *Resi Dali - Konfigurace* — tato runtime šablona záměrně nezapisuje do `H:65221` ani nespouští softwarový reset, takže může zůstat aktivní v projektu bez rizika náhodné rekonfigurace brány.

### Nastavení RTU-over-TCP

Protože šablona používá Modbus RTU spojení, nabízí se také importní parametr `IpAddress` pro instalace, kde TapHome dosáhne brány přes **sériově-IP most** (Moxa NPort, USR-TCP232) nebo přes **RESI-DALI-ETH v transparentním režimu RTU-over-Ethernet**. V tom případě nasměrujte `IpAddress` na IP mostu / ETH jednotky a všechna ostatní nastavení ponechejte stejná jako u RS-485 varianty. Pro čistý Modbus/TCP by byla přirozenější TCP-based šablona — tato Modbus RTU šablona konkrétně očekává rámcovanou RTU komunikaci.

> [!WARNING]
> **Pouze jeden Modbus master najednou.** Ani DALI ani Modbus RTU nearbitrují mezi souběžnými master-y. Pokud PLC, BMS nebo PC nástroj (například MODBUSConfigurator) také polluje bránu, dotazy gear-ů budou kolidovat a TapHome bude hlásit sporadické chyby *"Gear not responding!"*.

## Vztah ke konfigurační šabloně

Tatáž definice `Dali.xml` se s RESI bránou dodává jako **dvě komplementární TapHome šablony**, které pracují na různých fázích životního cyklu stejného hardwaru:

| Šablona | Fáze | Co dělá | Kdy použít |
|---------|------|---------|------------|
| **Resi Dali - Konfigurace** (`resi-dali-daliconfig`) | Jednorázové uvedení do provozu | Průvodce DALI 2.0 náhodným adresováním, per-adresa probe device-type, broadcast ON/OFF testy zdraví, **Resetovat krátké adresy** / **Delete short address** / **Change short address**, **Set Slave ID**, **Reset Gateway** | Nová instalace: přiřaďte krátké adresy 0–63 ovládacím zařízením, ověřte které adresy jsou obsazené |
| **Resi DALI** (`resi-dali-dali`, tato šablona) | Denní runtime řízení | Per-gear stmívání (64 gear-ů), skupinové stmívání (16 skupin), per-gear DALI 1.0 diagnostika, správa členství ve skupinách | Po uvedení do provozu: koncové řízení osvětlení |

**Typický průběh projektu:**

1. Zapojte a napájejte DALI sběrnici (RESI-DALI-PS) a bránu.
2. Importujte šablonu **Resi Dali - Konfigurace**, spusťte akci modulu *Resetovat krátké adresy* (*Confirm* = *Yes*), poté na průvodci *Find New Devices* vyberte *Start* — průvodce sám projde stavy *Skenovat krátkou adresu* → *Set SEARCHADDR* → *Kontrola* → *PROGRAM SHORT ADDRESS*, dokud se nezastaví na *Dokončit*; poté relaci ukončete přes *TERMINATE*. Ověřte přes *Gear 0..63* a *Turn On / Off All Lamps*.
3. Odstraňte modul **Resi Dali - Konfigurace** z projektu.
4. Importujte šablonu **Resi DALI** (tuto) na runtime řízení. Namapujte zařízení *Gear N* a *Group N* na TapHome scény, časovače a pravidla.

Obě šablony mohou také dočasně koexistovat — např. při přidávání nového gear-u do živé instalace — ale jen jedna by měla posílat Modbus komunikaci najednou. Runtime šablona záměrně vynechává akce rekonfigurace brány (Reset Gateway, Set Slave ID, broadcast ALL LEVEL), aby mohla zůstat v projektu bez rizika přepsání nastavení uvedení do provozu.

> [!TIP]
> Bezplatný DCA nástroj výrobce **MODBUSConfigurator** (Windows, dostupný ze stránky RESI) lze také použít pro uvedení do provozu místo TapHome šablony *Resi Dali - Konfigurace*. Runtime šablona *Resi DALI* funguje stejně bez ohledu na to, který nástroj byl použit pro přiřazení krátkých adres.

## Schopnosti zařízení

Šablona zpřístupňuje 80 DALI zařízení v TapHome, organizovaných ve dvou paralelních skupinách: 64 stmívačů *Gear* (jeden na každou DALI krátkou adresu) a 16 stmívačů *Group* (jeden na každou DALI skupinu). Jeden servisní atribut na úrovni modulu doplňuje obraz.

### Per-gear stmívání — Gear 0 … Gear 63

Každé z 64 servisních zařízení **Gear 0**, **Gear 1**, … **Gear 63** je TapHome stmívač, který cílí na jediné DALI ovládací zařízení při odpovídající krátké adrese. Zápisy jasu jdou do `H:510 LAMP LEVEL` (TapHome 0–100 % je škálováno lineárně do rozsahu DALI arc power, ohraničeného vlastní `MIN LEVEL` a `MAX LEVEL` gear-u); skutečná úroveň se zpětně čte z `H:511` přes DALI příkaz `QUERY ACTUAL LEVEL` (`0xA0`) a přeškáluje se zpět do 0–100 %.

Když šablona importuje gear, init script nejprve probuje gear přes `QUERY STATUS` (`0x90`); jakýkoliv bajt odpovědi dokazuje, že gear je přítomný, a uloží se jako jeho stav. Odpověď `0x8000` „bez odpovědi" označí gear jako *neodpovídající* (na náhodných 1–60 s) a v TapHome logu vypíše **„Gear not responding!"**. Pokud gear odpoví, init script dále přečte `QUERY MIN LEVEL` (`0xA2`) a `QUERY MAX LEVEL` (`0xA1`) a uloží výsledky do interního stavu pro periodický readscript.

Každý dotaz je chráněn před zastaralými a poškozenými odpověďmi: před každým dotazem šablona vyčte nepřečtenou odpověď, která zůstala v `H:511`, aby ji nepovažovala za odpověď na nový dotaz. Odpověď s úrovní, která není platnou úrovní (`0xFF`, `0x20FF` kolize na sběrnici, `0x8000` bez odpovědi) nebo leží mezi 1 a `MIN LEVEL` gear-u, se zamítne a zůstane poslední úroveň; změněná úroveň se přijme až po druhém stejném čtení. Servisní atributy úrovní místo neplatné hodnoty zobrazí `--`.

Každý gear zpřístupňuje 12 servisních atributů, které na požádání čtou DALI 1.0 / 2.0 dotazy:

| Servisní atribut | DALI příkaz | Hlásí |
|-----------------|-------------|-------|
| **Short Address** | (interní) | Krátká adresa (0–63), na kterou toto zařízení cílí — fixovaná v čase importu šablony |
| **Device Type** | `QUERY DEVICE TYPE` (`0x99`) | `DT{n}` (např. `DT0` fluorescenční, `DT6` LED, `DT8` barevný / tunable white) nebo `--` když bez odpovědi. Gear s více device typy odpoví `0xFF` (MASK); šablona je pak vypíše přes `QUERY NEXT DEVICE TYPE` (`0xA7`), např. `DT6, DT8`, nebo zobrazí `MASK`, když se nevrátí žádný typ |
| **Physical Min Level** | `QUERY PHYSICAL MIN LEVEL` (`0x9A`) | Hardwarem vynucená minimální úroveň stmívání v % |
| **Max Level** | `QUERY MAX LEVEL` (`0xA1`) | Nakonfigurovaná horní hranice použitá při škálování 0–100 % na DALI arc power |
| **Min Level** | `QUERY MIN LEVEL` (`0xA2`) | Nakonfigurovaná dolní hranice použitá při škálování 0–100 % na DALI arc power |
| **Power Up Level** | `QUERY POWER ON LEVEL` (`0xA3`) | Jas obnovený po opětovném napájení DALI sběrnice |
| **System Failure Level** | `QUERY SYSTEM FAILURE LEVEL` (`0xA4`) | Jas přijatý, když sběrnice ztratí komunikaci na >500 ms |
| **Groups** | `QUERY GROUPS 0-7` (`0xC0`) + `QUERY GROUPS 8-15` (`0xC1`) | Čárkami oddělený seznam DALI skupin, do kterých gear patří (`None` nebo např. `0,3,7`) |
| **DALI Status** | `QUERY STATUS` (`0x90`) | Dekódovaný stavový bajt s jeho surovou hodnotou: `OK`, když není nastaven žádný bit, jinak nastavené příznaky — `gear failure`, `lamp failure`, `lamp on`, `limit error`, `fade running`, `reset state`, `missing short address`, `power cycle` — např. `lamp on (0x04)`. Porucha přítomná od první odpovědi gear-u je označena `not raised: … reported since start` |
| **Fade** | `QUERY FADE TIME/FADE RATE` (`0xA5`) + `QUERY EXTENDED FADE TIME` (`0xA8`) | `fade time {n} ({t} s), fade rate {n}`; fade time `off`, když je 0, nebo `extended 0x..`, když gear místo něj používá rozšířený fade time |
| **DALI Version** | `QUERY VERSION NUMBER` (`0x97`) | `DALI-1` nebo `DALI-2 {major}.{minor}`, za kterým následuje surová hodnota v závorkách |
| **Bus statistics** | (interní čítače) | Čítače od startu: dotazy, vyčtené zastaralé odpovědi, bez odpovědi, kolize, zamítnuté úrovně |

Periodický readscript na každém gear-u čte aktuální arc úroveň (`0xA0`) a alespoň jednou za 60 čtecích cyklů polluje `QUERY STATUS` (`0x90`). Bit 0 stavového bajtu vyvolá **„Control gear failure!"** a bit 1 vyvolá **„Lamp failure!"** — vystavené jako TapHome warningy/chyby, takže porucha zářivkové trubice nebo vypadlý LED ovladač se zobrazí v aktivity logu bez manuálního pollování. Změněný bit poruchy se převezme až po druhém stejném čtení a ztracená odpověď se ještě jednou zopakuje, než se gear nahlásí jako **„Gear not responding!"**. Bity poruch, které gear hlásí v první odpovědi, se považují za jeho trvalý stav: zobrazí se v **DALI Status**, ale nevyvolají se, dokud se bit nevynuluje — pozdější porucha se pak vyvolá znovu. Porucha napájení se nevyvolává jako chyba; stavový bit se v **DALI Status** zobrazí jako `power cycle`.

### Akce konfigurace per-gear

Pět servisních akcí na každém *Gear N* zařízení zapisuje DALI konfigurační příkazy (auto-opakované do 100 ms přes `H:512 LAMP COMMAND + REPEAT`, jak vyžadují non-volatile DALI příkazy):

- **Add to Group** (parametr `Group ID` 0–15) — posílá `ADD TO GROUP` (`0x60+grp`), takže gear vstoupí do zvolené DALI skupiny a bude poslouchat následné broadcast zápisy skupiny.
- **Remove from Group** (parametr `Group ID` 0–15) — posílá `REMOVE FROM GROUP` (`0x70+grp`).
- **Reset to Default Settings** — posílá DALI `RESET` (`0x20`); obnoví všechny NVM parametry gear-u (max/min/power-on/system-failure level, členství ve skupinách, scény) na tovární default.
- **Set Startup Levels** — zachytí aktuální arc power a uloží ji jako Power On Level *i* System Failure Level v pořadí: `STORE ACTUAL LEVEL IN DTR` (`0x21`) → `STORE DTR AS POWER ON LEVEL` (`0x2C`) → `STORE DTR AS SYSTEM FAILURE LEVEL` (`0x2D`), každý s 10 ms mezerou.
- **Disable fading** (bez parametrů) — nahraje `0` do DALI registru přenosu dat (`0xA300` zapsané do `H:541`) a uloží ho v gear-u jako fade time (`0x2E`) a extended fade time (`0x30`), každý se 100 ms mezerou, takže změny úrovně se projeví bez přechodu. Aktuální hodnoty zobrazuje atribut **Fade**.

### Skupinové stmívání — Group 0 … Group 15

Každé z 16 servisních zařízení **Group 0**, **Group 1**, … **Group 15** je write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u patřícímu do té DALI skupiny, používající `H:520 GROUP LEVEL` (TapHome 0–100 % se násobí `0xFE` → DALI arc power 0–254). DALI nepovoluje bráně *zpětně číst* úroveň skupiny — sběrnice nese pouze broadcast zápis — takže TapHome drží poslední zapsanou hodnotu jako „aktuální" úroveň. Na zařízeních skupiny nejsou žádné init ani read scripty.

Každé zařízení *Group N* zpřístupňuje dvě servisní akce pro hromadnou správu členství:

- **Add All Lamps to Group** — broadcastuje `ADD TO GROUP` (`0x60+grp`) přes `H:532 ALL COMMAND + REPEAT`. **Každý gear na sběrnici** vstoupí do skupiny bez ohledu na svou aktuální krátkou adresu.
- **Remove All Lamps from Group** — broadcastuje `REMOVE FROM GROUP` (`0x70+grp`). Každý gear opustí skupinu.

> [!TIP]
> Použijte skupinové stmívání pro „kuchyňská světla", „obývací downlighty" nebo libovolnou zónu, kde má více gear-ů sledovat jediný stmívač. Skupinové zápisy jsou mnohem efektivnější než paralelní řízení jednotlivých gear-ů — jediná Modbus transakce dosáhne až 64 gear-ů současně.

### Diagnostika na úrovni modulu

Modul zpřístupňuje jediný servisní atribut:

- **Slave ID** — čte Modbus Unit ID uložené ve FLASH registru `H:65221`. Aktivní pouze když `DIP4 = OFF`; při `DIP4 = ON` brána vynutí adresu 255 bez ohledu na FLASH hodnotu. Použijte k ověření adresy brány před přidáváním dalších zařízení, zejména po kole uvedení do provozu, které zapsalo nestandardní ID.

## Řešení problémů

### „Gear not responding!" na známém adresovaném gear-u

1. Ověřte napětí DALI sběrnice na gear-u: 11,5–22,5 V (typicky 14–16 V). Nižší hodnoty obvykle indikují zkrat nebo sběrnici, která je příliš dlouhá pro průřez kabelu (viz *Topologie DALI sběrnice*).
2. Zkontrolujte LED **ERR** na RESI-DALI-PS — pokud svítí, sběrnice je ve zkratu, přetížená nebo PSU je vadný.
3. Spusťte znovu probování *Gear N* v sesterské šabloně *Resi Dali - Konfigurace* — runtime šablona zkouší znovu jen po náhodné pauze až 60 s, konfigurační šablona dává okamžité pass/fail per adresu.
4. Ověřte, zda gear vůbec má krátkou adresu. Pokud byl vyměněn nebo továrně resetován na sběrnici, bude bez adresy a musí být znovu uveden do provozu přes *Resi Dali - Konfigurace*.

### Skupinové stmívání nemá efekt

1. Ověřte, že alespoň jeden gear je členem skupiny — otevřete *Gear N → Groups* na každém podezřelém členu a zkontrolujte, zda se ID skupiny objevuje v čárkami odděleném seznamu.
2. Pokud chybí členství, spusťte akci **Add to Group** na každém gear-u jednotlivě, nebo použijte **Add All Lamps to Group** na zařízení skupiny pro broadcast po celé sběrnici.
3. Pamatujte, že **Group N** je write-only — slider stmívače v TapHome ukládá poslední zapsanou hodnotu, ale neodráží skutečný stav sběrnice. Pokud jsou gear-y vypnuté, příkaz úrovně skupiny na nich nemá efekt.

### Porucha lampy / porucha napájení nejsou hlášeny

1. Otevřete atribut **DALI Status** gear-u. Pokud končí na `not raised: … reported since start`, porucha byla přítomná už v první odpovědi gear-u a považuje se za jeho trvalý stav — zobrazí se, ale nevyvolá se, dokud se bit jednou nevynuluje.
2. Porucha napájení se jako chyba nevyvolává vůbec; stavový bit se v **DALI Status** zobrazí jako `power cycle`.
3. Nová porucha se objeví až poté, co se stav pollne (alespoň jednou za 60 čtecích cyklů) a dvakrát se přečte stejně, takže krátké probliknutí bitu poruchy se nehlásí.

### Sporadické Modbus chyby po uvedení do provozu

1. Ujistěte se, že žádný jiný Modbus master (MODBUSConfigurator, PLC, BMS) souběžně nepolluje bránu. DALI a Modbus nearbitrují mezi master-y. Atribut **Bus statistics** na každém gear-u počítá od startu vyčtené zastaralé odpovědi, chybějící odpovědi, kolize a zamítnuté úrovně — počty, které stále rostou, ukazují na souběžnou komunikaci na bráně nebo na DALI sběrnici.
2. Ověřte, že `RS485 GND` je připojen mezi bránou a společnou zemí TapHome napájecího zdroje — chybějící GND je nejčastější chyba RS-485 na dlouhých linkách.
3. Pro RTU-over-TCP přes sériový most potvrďte, že most běží v rámcovém RTU režimu (ne raw TCP socket) a že mezi-znaková mezera na sériové straně respektuje časování 9600 baud 8N1.
4. Pokud se symptomy objevily po změně Slave ID přes šablonu *Resi Dali - Konfigurace*, znovu importujte tuto runtime šablonu s novým importním parametrem `SlaveId` — předchozí importovaný modul stále polluje na staré adrese.

## Dostupná zařízení 80

Tato zařízení se po importu zobrazí v TapHome.

Resi DALI Modul

Servisní atributy

|          |                                                                                                                                                                           |
|----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Slave ID | Čte Modbus Unit ID uložené ve FLASH registru H:65221 — aktivní pouze když DIP4=OFF (tovární default 255). Použijte k ověření adresy brány před přidáním dalších zařízení. |

Servisní atributy

${xml\_slave\_id}

```taphome
modbusr(H,65221,uint16)
```

Gear 0 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 0 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 1 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 1 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 2 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 2 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 3 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 3 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 4 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 4 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 5 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 5 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 6 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 6 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 7 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 7 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 8 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 8 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 9 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 9 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 10 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 10 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 11 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 11 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 12 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 12 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 13 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 13 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 14 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 14 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 15 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 15 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 16 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 16 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 17 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 17 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 18 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 18 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 19 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 19 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 20 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 20 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 21 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 21 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 22 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 22 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 23 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 23 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 24 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 24 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 25 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 25 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 26 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 26 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 27 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 27 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 28 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 28 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 29 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 29 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 30 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 30 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 31 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 31 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 32 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 32 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 33 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 33 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 34 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 34 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 35 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 35 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 36 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 36 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 37 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 37 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 38 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 38 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 39 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 39 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 40 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 40 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 41 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 41 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 42 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 42 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 43 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 43 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 44 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 44 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 45 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 45 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 46 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 46 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 47 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 47 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 48 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 48 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 49 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 49 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 50 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 50 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 51 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 51 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 52 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 52 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 53 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 53 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 54 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 54 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 55 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 55 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 56 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 56 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 57 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 57 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 58 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 58 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 59 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 59 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 60 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 60 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 61 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 61 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 62 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 62 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Gear 63 Stmívač Čtení i zápis

DALI ovládací zařízení při krátké adrese 63 — TapHome stmívač namapovaný na DALI arc power 0–100 % přes H:510 LAMP LEVEL (zápis) a QUERY ACTUAL LEVEL přes H:511 (čtení), ohraničený vlastní MIN / MAX LEVEL gear-u.

Registr: H:511 → H:510 UInt16 Jednotka: % numeric

Servisní atributy

|                       |                                                                                                                                                                            |
|-----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Krátká adresa         | DALI krátká adresa (0–63) cílená tímto zařízením — fixovaná v čase importu šablony a použitá v horním bytu každého Modbus zápisu.                                          |
| Device Type           | DALI byte device-type vrácený přes QUERY DEVICE TYPE (0x99) — hlásí DT0 (fluorescenční), DT6 (LED ovladač), DT8 (barevný / tunable white) atd., nebo -- když bez odpovědi. |
| Physical Min Level    | Hardwarem vynucená minimální úroveň stmívání, kterou gear hlásí — čteno z QUERY PHYSICAL MIN LEVEL (0x9A), v procentech.                                                   |
| Max Level             | Nakonfigurovaný DALI MAX LEVEL — čteno z QUERY MAX LEVEL (0xA1); použito jako horní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Min Level             | Nakonfigurovaný DALI MIN LEVEL — čteno z QUERY MIN LEVEL (0xA2); použito jako dolní hranice při škálování TapHome 0–100 % na DALI arc power.                               |
| Power Up Level        | Jas obnovený po obnově napájení DALI sběrnice — čteno z QUERY POWER ON LEVEL (0xA3).                                                                                       |
| System Failure Level  | Jas přijatý, když DALI sběrnice ztratí komunikaci na více než 500 ms — čteno z QUERY SYSTEM FAILURE LEVEL (0xA4).                                                          |
| Skupiny               | Čárkami oddělený seznam DALI skupin (0–15), do kterých gear patří — dekódovaný z QUERY GROUPS 0-7 (0xC0) a QUERY GROUPS 8-15 (0xC1); zobrazuje None nebo např. 0,3,7.      |
| Support Lamp Failure  | Zda lampa / ovladač podporuje detekci poruchy lampy — Yes / No / --. Kontroluje chybu Lamp failure! v periodickém readscriptu.                                             |
| Support Power Failure | Zda lampa / ovladač podporuje detekci poruchy napájení — Yes / No / --. Kontroluje chybu Power failure! v periodickém readscriptu.                                         |
| DALI Version          |                                                                                                                                                                            |
| Bus statistics        |                                                                                                                                                                            |

Servisní akce

|                           |                                                                                                                                                                                                                  |
|---------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add to Group              | Přidá tento gear do DALI skupiny (0–15) přes ADD TO GROUP (0x60+grp) — auto-opakováno do 100 ms, jak vyžadují DALI konfigurační příkazy.                                                                         |
| Remove from Group         | Odstraní tento gear z DALI skupiny (0–15) přes REMOVE FROM GROUP (0x70+grp).                                                                                                                                     |
| Reset to Default Settings | Posílá DALI RESET (0x20) — obnoví každý NVM parametr gear-u (max / min / power-on / system-failure level, členství ve skupinách, scény) na tovární default.                                                      |
| Set Startup Levels        | Zachytí aktuální arc power a uloží ji jako Power On Level a System Failure Level — posloupnost STORE ACTUAL LEVEL IN DTR (0x21) → STORE DTR AS POWER ON LEVEL (0x2C) → STORE DTR AS SYSTEM FAILURE LEVEL (0x2D). |
| Disable fading            |                                                                                                                                                                                                                  |

Čtení (modul)

```taphome
var x := 0; var rx := 0; var y := 0;
if Status > 0
    Status := Status - 1;
    adderror(3, "Gear not responding!");
    return(0);
end

# checkStatus: ReadLevel resets it while the gear answers; statusPoll: QUERY STATUS at least once per 60 runs
checkStatus := checkStatus - 1;
statusPoll := statusPoll - 1;
if checkStatus < 1 or statusPoll < 1
    # an unread answer left in the gateway would be taken for this query: read it away and count it
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    # a single lost answer happens on DALI: ask once more before declaring the gear missing
    if x = 0x8000
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    end
    if x <= 0xFF
        # a changed failure bit must be read twice the same before it is taken
        if statusSeen = 1 and getbits(x, 0, 2) != getbits(gearStatus, 0, 2)
            y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
            modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
            if y != x
                cntBad := cntBad + 1;
                x := gearStatus;
            end
        end
        if statusSeen = 0
            ignGear := getbit(x, 0);
            ignLamp := getbit(x, 1);
            statusSeen := 1;
        end
        # a bit that clears ends its ignore, so a later failure is raised
        if (getbit(x, 0) = 0, ignGear := 0);
        if (getbit(x, 1) = 0, ignLamp := 0);
        gearStatus := x;
        checkStatus := 60;
        statusPoll := 60;
    else
        if x = 0x8000
            Status := RANDINT(10, 60);
            adderror(3, "Gear not responding!");
            return(0);
        end
    end
end

# messages last one run only, so they are raised from the stored status on every run
if ((getbit(gearStatus, 0) = 1) and (ignGear = 0), adderror(1, "Control gear failure!"));
if ((getbit(gearStatus, 1) = 1) and (ignLamp = 0), adderror(2, "Lamp failure!"));
```

Inicializace

```taphome
var x := 0; var rx := 0;
# QUERY STATUS 0x90: every reply byte proves the gear is present; 0x8000 = no answer, 0x20FF = bus collision
# an unread answer left in the gateway would be taken for this query: read it away and count it
x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
x := modbusr(SH, 511, uint16);
cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
statusSeen := 0;
if x <= 0xFF
    # failure bits a gear reports from its first answer are its permanent state, not an event: shown, not raised
    gearStatus := x;
    ignGear := getbit(x, 0);
    ignLamp := getbit(x, 1);
    statusSeen := 1;
    Status := 0;
else
    Status := RANDINT(1, 60);
end

if Status = 0
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, minLevel := x);

    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x <= 0xFE, maxLevel := x);
end
```

Čtení úrovně

```taphome
var x := 0; var rx := 0; var y := 0;
if Status = 0
    if minLevel = 0
        # an unread answer left in the gateway would be taken for this query: read it away and count it
        x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        x := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
        if (x <= 0xFE, minLevel := x);
    end
    x := modbusr(SH, 511, uint16); if (x != 0x8000, cntStale := cntStale + 1);
    modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    cntQ := cntQ + 1; if (x = 0x8000, cntNone := cntNone + 1); if (x = 0x20FF, cntColl := cntColl + 1);
    if (x != 0x8000 or rx, checkStatus := 60);
    # 0xFF = MASK, 0x20FF = collision, 0x8000 = no answer: keep the last level instead of a phantom value
    if x > 0xFE
        return(Le);
    end
    # an actual level is 0 or between the gear's min and max: anything else is not this gear's answer
    if x > 0 and x < minLevel
        cntBad := cntBad + 1;
        return(Le);
    end
    # a changed level must be read twice the same before it is taken
    if x != lastRaw
        y := modbusr(SH, 511, uint16); if (y != 0x8000, cntStale := cntStale + 1);
        modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA0);
        sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        y := modbusr(SH, 511, uint16);
        cntQ := cntQ + 1; if (y = 0x8000, cntNone := cntNone + 1); if (y = 0x20FF, cntColl := cntColl + 1);
        if y != x
            cntBad := cntBad + 1;
            return(Le);
        end
        lastRaw := x;
    end
    return(if(x = 0, 0, linear(x, minLevel, 0.01, maxLevel, 1)));
else
    return(NaN);
end
```

Zápis úrovně

```taphome
var level := 0;
if(Le > 0, level := round(linear(Le, 0.01, minLevel, 1, maxLevel)));
modbusw(SH, 510, uint16, (ShortAddress << 8) + level );
```

Servisní atributy

${xml\_short\_address}

```taphome
ShortAddress
```

${xml\_device\_type}

```taphome
var x := 0; var y := 0; var rx := 0; var s := ""; var i := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x99);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    x := modbusr(SH, 511, uint16);
    if (x < 0xFF, return("DT" + x));
    if x = 0xFF
        while i < 8
            modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA7);
            sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
            y := modbusr(SH, 511, uint16);
            if y < 0xFE
                s := if(s = "", "DT" + y, s + ", DT" + y);
                i := i + 1;
            else
                i := 8;
            end
        loop
        return(if(s = "", "MASK", s));
    end
end

return("--")
```

Physical Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x9A);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Max Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA1);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Min Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA2);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

Power Up Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA3);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

System Failure Level

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA4);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if (x <= 0xFE, return(round((x / 0xFE) * 100) + " %"));
end

return("--")
```

${xml\_groups}

```taphome
var x := 0; var rx := 0;
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC0);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g1 := modbusr(SH, 511, uint16);
    if (g1 > 0xFF, return("--")); 

    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xC1);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var g2 := modbusr(SH, 511, uint16);
    if (g2 > 0xFF, return("--")); 

    var ret := "";

    if (getbit(g1, 0), ret := ret + "0");
    if (getbit(g1, 1), if (ret = "", ret := "1", ret := ret + ",1"));
    if (getbit(g1, 2), if (ret = "", ret := "2", ret := ret + ",2"));
    if (getbit(g1, 3), if (ret = "", ret := "3", ret := ret + ",3"));
    if (getbit(g1, 4), if (ret = "", ret := "4", ret := ret + ",4"));
    if (getbit(g1, 5), if (ret = "", ret := "5", ret := ret + ",5"));
    if (getbit(g1, 6), if (ret = "", ret := "6", ret := ret + ",6"));
    if (getbit(g1, 7), if (ret = "", ret := "7", ret := ret + ",7"));
    if (getbit(g2, 0), if (ret = "", ret := "8", ret := ret + ",8"));
    if (getbit(g2, 1), if (ret = "", ret := "9", ret := ret + ",9"));
    if (getbit(g2, 2), if (ret = "", ret := "10", ret := ret + ",10"));
    if (getbit(g2, 3), if (ret = "", ret := "11", ret := ret + ",11"));
    if (getbit(g2, 4), if (ret = "", ret := "12", ret := ret + ",12"));
    if (getbit(g2, 5), if (ret = "", ret := "13", ret := ret + ",13"));
    if (getbit(g2, 6), if (ret = "", ret := "14", ret := ret + ",14"));
    if (getbit(g2, 7), if (ret = "", ret := "15", ret := ret + ",15"));

    if (ret = "", return("None"), return(ret));
else
    return("--");
end
```

DALI Status

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x90);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var s := "";
        if (getbit(x, 0), s := if(s = "", "gear failure", s + ", gear failure"));
        if (getbit(x, 1), s := if(s = "", "lamp failure", s + ", lamp failure"));
        if (getbit(x, 2), s := if(s = "", "lamp on", s + ", lamp on"));
        if (getbit(x, 3), s := if(s = "", "limit error", s + ", limit error"));
        if (getbit(x, 4), s := if(s = "", "fade running", s + ", fade running"));
        if (getbit(x, 5), s := if(s = "", "reset state", s + ", reset state"));
        if (getbit(x, 6), s := if(s = "", "missing short address", s + ", missing short address"));
        if (getbit(x, 7), s := if(s = "", "power cycle", s + ", power cycle"));
        var ign := if((ignGear = 1) and (ignLamp = 1), "gear and lamp failure", if(ignGear = 1, "gear failure", if(ignLamp = 1, "lamp failure", "")));
        return(if(s = "", "OK", s) + " (0x" + tostring(x, "X2") + ")" + if(ign = "", "", "; not raised: " + ign + " reported since start"));
    end
end

return("--")
```

Fade

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA5);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        var t := getbits(x, 4, 4);
        var ret := if(t = 0, "off", t + " (" + round(sqrt(power(2, t)) * 5) / 10 + " s)");
        modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0xA8);
    sleep(5); rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
        var e := modbusr(SH, 511, uint16);
        if (t = 0 and e <= 0xFF and e != 0, ret := "extended 0x" + tostring(e, "X2"));
        return("fade time " + ret + ", fade rate " + getbits(x, 0, 4));
    end
end

return("--")
```

DALI Version

```taphome
if Status = 0
    modbusr(SH, 511, uint16); modbusw(SH, 511, uint16, (ShortAddress << 8) + 0x97);
    sleep(5); var rx := getbits(modbusr(SH, 550, uint16), 0, 2); if(rx, 0, sleep(50));
    var x := modbusr(SH, 511, uint16);
    if x <= 0xFF
        return(if(x >= 8, "DALI-2 " + getbits(x, 2, 6) + "." + getbits(x, 0, 2), "DALI-1") + " (" + x + ")");
    end
end

return("--")
```

Bus statistics

```taphome
return("since start: queries " + cntQ + ", stale answers read away " + cntStale + ", no answer " + cntNone + ", collisions " + cntColl + ", rejected levels " + cntBad)
```

Servisní akce

${xml\_add\_to\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x60 + grp);
```

${xml\_remove\_from\_group}

Parametry: Group ID (0–15 grp)

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x70 + grp);
```

${xml\_reset\_to\_default\_settings}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x20);
```

${xml\_set\_startup\_levels}

```taphome
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x21);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2c);
sleep(10);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2d);
```

Disable fading

```taphome
modbusw(SH, 541, uint16, 0xA300);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x2E);
sleep(100);
modbusw(SH, 512, uint16, (ShortAddress << 8) + 0x30);
```

Group 0 Stmívač Čtení i zápis

DALI broadcast skupina 0 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 0;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 0;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 0;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 1 Stmívač Čtení i zápis

DALI broadcast skupina 1 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 1;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 1;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 1;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 2 Stmívač Čtení i zápis

DALI broadcast skupina 2 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 2;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 2;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 2;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 3 Stmívač Čtení i zápis

DALI broadcast skupina 3 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 3;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 3;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 3;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 4 Stmívač Čtení i zápis

DALI broadcast skupina 4 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 4;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 4;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 4;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 5 Stmívač Čtení i zápis

DALI broadcast skupina 5 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 5;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 5;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 5;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 6 Stmívač Čtení i zápis

DALI broadcast skupina 6 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 6;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 6;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 6;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 7 Stmívač Čtení i zápis

DALI broadcast skupina 7 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 7;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 7;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 7;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 8 Stmívač Čtení i zápis

DALI broadcast skupina 8 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 8;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 8;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 8;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 9 Stmívač Čtení i zápis

DALI broadcast skupina 9 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 9;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 9;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 9;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 10 Stmívač Čtení i zápis

DALI broadcast skupina 10 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 10;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 10;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 10;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 11 Stmívač Čtení i zápis

DALI broadcast skupina 11 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 11;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 11;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 11;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 12 Stmívač Čtení i zápis

DALI broadcast skupina 12 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 12;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 12;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 12;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 13 Stmívač Čtení i zápis

DALI broadcast skupina 13 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 13;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 13;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 13;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 14 Stmívač Čtení i zápis

DALI broadcast skupina 14 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 14;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 14;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 14;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

Group 15 Stmívač Čtení i zápis

DALI broadcast skupina 15 (0–15) — write-only TapHome stmívač, který broadcastuje jednu hodnotu arc-power každému gear-u v této skupině přes H:520 GROUP LEVEL. Sběrnice nevrací úrovně skupin, takže TapHome drží poslední zapsanou hodnotu.

UInt16 Jednotka: % numeric

Servisní akce

|                             |                                                                                                                                                        |
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|
| Add All Lamps to Group      | Broadcastuje ADD TO GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici vstoupí do této skupiny bez ohledu na svou aktuální krátkou adresu. |
| Remove All Lamps from Group | Broadcastuje REMOVE FROM GROUP přes H:532 ALL COMMAND + REPEAT — každý gear na sběrnici opustí tuto skupinu.                                           |

Zápis úrovně

```taphome
var GroupAddress := 15;
modbusw(SH, 520, uint16, (GroupAddress << 8) + (Le * 0xFE));
```

Servisní akce

${xml\_add\_to\_group\_all\_lamps}

```taphome
var GroupAddress := 15;
modbusw(SH, 532, uint16, 0x60 + GroupAddress)
```

${xml\_remove\_from\_group\_all\_lamps}

```taphome
var GroupAddress := 15;
modbusw(SH, 532, uint16, 0x70 + GroupAddress)
```

**Připojení:** Modbus RTU • 9600 baud• 8N1 • Slave ID: $\[SlaveId]

Možná vylepšení (23)

- H:531 ALL COMMAND (broadcast DALI command) — Single-shot broadcast DALI command (no repeat). Template uses H:532 (ALL COMMAND + REPEAT) for group membership but never exposes plain ALL OFF / ALL ON / ALL ARC POWER as a service action — turn-on/off-all are not present (sibling daliconfig template has them via H:530)
- H:530 ALL LEVEL (broadcast arc power) — Sets brightness for every gear in one Modbus write. Convenient 'turn off all lamps' / 'turn on all lamps' shortcut — implemented in the sibling daliconfig template, missing in this operational template
- H:521 GROUP COMMAND (per-group DALI command) — Per-group DALI command (single-shot). Could expose group-level OFF / RECALL MIN / RECALL MAX / GO TO SCENE as service actions on each Group device, but template only writes H:520 GROUP LEVEL
- H:522 GROUP COMMAND + REPEAT — Per-group DALI configuration command (auto-repeated within 100 ms). Required for STORE DTR AS GROUP SCENE etc. — not exposed as a service action
- H:541 DIRECT 16-BIT FRAME — Raw DALI 1.0 frame send. Used by sibling daliconfig template for the DALI 2.0 random-addressing algorithm; not needed for runtime brightness control
- I:10020-I:10027 DALI 24-BIT FRAME — DALI 2.0 24-bit frames — required for DT8 colour control (XY, colour temperature, RGBW), DALI 2.0 control gear queries, and DALI-2 input devices (push-buttons, presence detectors). Template exposes only DALI 1.0 brightness layer per gear
- I:10030-I:10047 DALI 25-BIT eDALI FRAME — Lunatone-proprietary 25-bit eDALI frames (auto and user redundant-bit variants). Not used by any DALI 1.0 gear
- I:10050-I:10067 DALI 28-BIT / 32-BIT FRAME — Extended DALI 2.0 frames (memory bank access, DALI-2 application controllers). Template scope is single-channel arc power per gear
- H:500 (DSI VALUE) DSI 8-bit value send — Send a raw 8-bit DSI/DALI value with no addressing (bus-level diagnostics). Bypassed by every TapHome script
- C:0 / H:551 DALI Bus Error — 1 = DALI bus fault / short circuit / missing PSU. Useful diagnostic — could be added as a module-level service attribute. Currently bus errors only surface indirectly through 'Gear not responding!' errors emitted by per-gear readscripts
- H:100 DALI PRIORITY SLOT — 0..4 → 12-16 ms forward-frame timing. Default 2 (configuration). Bus-tuning parameter; template runs at default
- H:6000 DIP SWITCH / SOFTWARE RESET — Read returns the 4 DIP switch values; write 1 reboots the gateway. Sibling daliconfig template exposes Reset Gateway / Set Slave ID; this runtime template intentionally does not (commissioning concern)
- H:65222 / H:65224 / H:65225 BAUD\_RATE / PARITY / STOP\_BITS (FLASH) — FLASH-stored serial parameters. Template hard-codes 9600 8N1 in connection\_details, so these are out of scope
- I:0 / I:50-I:53 / scenes DALI 1.0 scenes (recall / store / query) — DALI 1.0 standard supports 16 stored scenes per gear/group recallable via GO TO SCENE (0x10..0x1F) and storable via STORE DTR AS SCENE (0x40..0x4F). Template exposes per-gear ADD/REMOVE FROM GROUP and RESET, but no scene recall/store/remove/query actions
- H:512 (RECALL MAX/MIN/GOTO LAST/UP/DOWN/STEP) DALI 1.0 high-level commands per gear — RECALL MAX LEVEL (0x05), RECALL MIN LEVEL (0x06), UP (0x01), DOWN (0x02), STEP UP (0x03), STEP DOWN (0x04), GO TO LAST ACTIVE LEVEL (0x0A) — useful as service actions for visual feedback / smooth dimming. Not exposed; brightness goes only through linear scaling
- H:512 (STORE DTR AS MAX/MIN/POWER ON/SYSTEM FAILURE LEVEL) Per-gear configuration write commands — STORE DTR AS MAX LEVEL (0x2A), STORE DTR AS MIN LEVEL (0x2B), STORE DTR AS POWER ON LEVEL (0x2C), STORE DTR AS SYSTEM FAILURE LEVEL (0x2D), STORE DTR AS FADE TIME / FADE RATE — template has 'Set Startup Levels' (combines 0x21, 0x2C, 0x2D) but does NOT expose individual writes for max/min/fade-time/fade-rate
- H:511 (QUERY FADE TIME / FADE RATE / RANDOM ADDRESS / EXT VERSION) Additional DALI queries — QUERY FADE TIME / FADE RATE (0xA5), QUERY VERSION NUMBER (0x97), QUERY RANDOM ADDRESS H/M/L (0x98/0xC2/0xC3), QUERY CONTENT DTR/DTR1/DTR2 — not exposed in service attributes, only the 10 attributes listed per gear are populated
- H:511 (QUERY CONTROL GEAR / RESET STATE / LIMIT ERROR / LAMP POWER ON / MISSING SHORT ADDRESS) DALI gear health / topology queries — QUERY CONTROL GEAR (0x90), QUERY RESET STATE (0x95), QUERY LIMIT ERROR (0x94), QUERY LAMP POWER ON (0x93), QUERY MISSING SHORT ADDRESS (0x96, broadcast) — diagnostic queries. Could be useful as module-level diagnostics; template exposes only QUERY STATUS / LAMP FAILURE / POWER FAILURE / DEVICE TYPE / MIN-MAX-PHYSICAL MIN-POWER UP-SYSTEM FAILURE LEVEL / GROUPS
- H:511 (READ MEMORY LOCATION 0xC5) DALI memory bank read — READ MEMORY LOCATION (0xC5) is required to read DALI 2.0 memory banks (Bank 0 device GTIN, FW version, serial number; Bank 1 for emergency lighting). Not used
- ASCII protocol commands Parallel ASCII text protocol — RESI gateway also exposes a CR-terminated text protocol (#LARC, #GARC, #AARC, #LGS, #LCMD, #LCMDA, #DALI CMDxx etc.). Template uses Modbus exclusively — ASCII would only matter for diagnostics/terminal access
- DT6 fade time / fade rate / DAPC sequence Smooth dimming primitives — DAPC (Direct Arc Power Control) sequence allows fast continuous level updates for smooth dimming. Each gear has stored fade time / fade rate that affect transitions. Template writes raw arc power without configuring fade behaviour
- DT8 colour control (XY, colour temperature, RGBW) DALI DT8 tunable white / RGB / RGBW — DT8 colour control gears (tunable white CCT, XY colour, RGBW) require DALI 2.0 24-bit frames sent via H:541 / I:10020. Template exposes plain ModbusDimmer per gear — for DT8 lamps use a dedicated DT8 template
- DT1 emergency lighting DALI DT1 self-contained emergency lights — Emergency-luminaire device type with periodic self-tests (function/duration test) and battery state queries. Out of scope — template is general-purpose dimming

## Parametry importu

Tyto hodnoty zadáte při importu XML.

| Ptá se v aplikaci | Výchozí       |
|-------------------|---------------|
| Slave ID          | `255`         |
| IP adresa         | `192.168.1.0` |

## Zdroje

- RESI-DALI-SIO/ETH Modbus & ASCII protocol reference
  
  [www.resi.cc](https://www.resi.cc/resi/docs/RESI-L-DALI-SIO,ETH-MODBUS+ASCII-EN.pdf) 2026-04-25
  
  [PDF](https://taphome.com/compatibility/devices/resi-dali-dali/manufacturer/RESI-L-DALI-SIO,ETH-MODBUS+ASCII-EN.pdf)
- RESI-xxx-SIO, RESI-xxx-ETH hardware & software manual (DALI chapter)
  
  [www.resi.cc](https://www.resi.cc/resi/docs/RESI-M-xxx-SIO-ETH-EN.pdf) 2026-04-25
  
  [PDF](https://taphome.com/compatibility/devices/resi-dali-dali/manufacturer/RESI-M-xxx-SIO-ETH-EN.pdf)
- RESI-DALI-SIO datasheet (GW-28)
  
  [www.resi.cc](https://www.resi.cc/resi/catalog/files/RESI-CATALOG-GATEWAYS-EN-Pages/RESI-CATALOG-GATEWAYS-EN-GW-28-RESI-DALI-SIO.pdf) 2026-04-25
  
  [PDF](https://taphome.com/compatibility/devices/resi-dali-dali/manufacturer/RESI-CATALOG-GATEWAYS-EN-GW-28-RESI-DALI-SIO.pdf)
- RESI-DALI-ETH datasheet (GW-29)
  
  [www.resi.cc](https://www.resi.cc/resi/catalog/files/RESI-CATALOG-GATEWAYS-EN-Pages/RESI-CATALOG-GATEWAYS-EN-GW-29-RESI-DALI-ETH.pdf) 2026-04-25
  
  [PDF](https://taphome.com/compatibility/devices/resi-dali-dali/manufacturer/RESI-CATALOG-GATEWAYS-EN-GW-29-RESI-DALI-ETH.pdf)
- RESI-DALI-PS datasheet (GW-30)
  
  [www.resi.cc](https://www.resi.cc/resi/catalog/files/RESI-CATALOG-GATEWAYS-EN-Pages/RESI-CATALOG-GATEWAYS-EN-GW-30-RESI-DALI-PS.pdf) 2026-04-25
  
  [PDF](https://taphome.com/compatibility/devices/resi-dali-dali/manufacturer/RESI-CATALOG-GATEWAYS-EN-GW-30-RESI-DALI-PS.pdf)
- RESI-DALI-SIO,ETH,PS product page
  
  [www.resi.cc](https://www.resi.cc/prestashop/en/home/1-resi-dali-sioethps.html) 2026-04-25

Dokumenty výrobců jsou © jejich příslušných vlastníků. Poskytujeme je tak, jak je výrobce zveřejnil, pouze pro informaci.

## Související dokumentace

- [Modbus Integration](https://taphome.com/cs/compatibility/modbus-guide/)
- [Modbus](https://taphome.com/cs/docs/integration/modbus/)
- [Jednoduché nastavení pomocí šablon](https://taphome.com/cs/docs/integration/modbus/templates/)
- [Skripty Modbus a prefetch](https://taphome.com/cs/docs/script/modbus-scripts/)
- [Funkce Modbus](https://taphome.com/cs/docs/script/modbus/)
- [Datové typy Modbus](https://taphome.com/cs/docs/script/modbus-data-types/)

## Řešení problémů

Časté problémy související s tímto tématem:

- [Světla DALI se sama zapínají](https://taphome.com/cs/troubleshooting/wiring/dali-lights-switch-on-by-themselves/) — Světla DALI za bránou DALI se bez jakéhokoli příkazu zapnou na minimum nebo změní jas, většinou pokaždé stejných pár světel. Sběrnice je na okamžik rušená — bránou, zkratem na jedné větvi nebo poklesem napětí.

[Zobrazit všechny články řešení problémů](https://taphome.com/cs/troubleshooting/)

