Registry API#

Centralny rejestr obiektów vCLU. Każdy obiekt z om.lua (lokalny lub zdalny) trafia do rejestru i jest dostępny przez globalny alias _.

Globalne struktury#

NazwaTypOpis
_registrytableGłówna tablica — klucz to pełna ścieżka (np. "CLU221000290.DOU1234")
_nameIndextableMapa nazw na ścieżki ("Lampa" → "CLU.DOU1")
_tagIndextableMapa tagów na tablice obiektów
_aliasGlobalny skrót do _registry

Metody rejestru#

_:get(pathOrName) — pobranie obiektu#

local obj = _:get("CLU.DOUT1")
local obj = _:get("Lampa")        -- po nazwie
if obj then obj:on() end

Parametry:

  • pathOrName (string) — ścieżka obiektu lub nazwa

Zwraca: table|nil — instancja obiektu lub nil

Rozwiązywanie ścieżek: jeśli argument zawiera . — traktowany jako pełna ścieżka; w przeciwnym razie szukany w _nameIndex.


_:sync(pathOrName, value) — synchronizacja stanu#

_:sync("CLU.DOUT1", 1)
_:sync("Lampa", 0)

Parametry:

  • pathOrName (string) — ścieżka lub nazwa obiektu
  • value (any) — nowa wartość stanu

Zachowanie:

  1. Rozwiązuje ścieżkę/nazwę
  2. Wywołuje obj:updateState(value) (lub ustawia obj._lastState)
  3. Automatycznie konwertuje string-liczby na wartości numeryczne ("1"1)
  4. Emituje "state_changed" na StateBus z danymi: {path, value, oldValue, type, obj}

Typowe użycie — w om.lua na prawdziwym CLU:

DOUT.OnSwitchOn  VCLU:execute(0, "_:sync('CLU123.DOUT1', 1)")
DOUT.OnSwitchOff  VCLU:execute(0, "_:sync('CLU123.DOUT1', 0)")

_:event(eventPath) — emisja zdarzenia#

_:event("CLU.DIN1.OnClick")
_:event("CLU.DOUT1.OnSwitchOn")

Parametry:

  • eventPath (string) — pełna ścieżka w formacie "ObjectPath.EventName"

Zachowanie:

  1. Parsuje ścieżkę wzorcem "(.+)%.([^.]+)$" → obiekt + nazwa eventu
  2. Rozwiązuje ścieżkę obiektu
  3. Wywołuje obj:emit(eventName)

_:byTag(tag) — obiekty po tagu#

local lights = _:byTag("lights")
lights:on()

Parametry:

  • tag (string) — nazwa tagu

Zwraca: RemoteGroup — grupa obiektów z danym tagiem (pusta jeśli tag nie istnieje)


_:byTags(...) — obiekty po wielu tagach#

local group = _:byTags("salon", "lights")
group:setValue(50)

Parametry:

  • ... (string) — dowolna liczba tagów (operacja OR — suma zbiorów)

Zwraca: RemoteGroup — zdeduplikowana grupa obiektów pasujących do dowolnego tagu


_:tags() — lista tagów#

local allTags = _:tags()
for _, tag in ipairs(allTags) do
    print(tag)
end

Zwraca: table — tablica nazw tagów


_:list() — lista obiektów#

local all = _:list()
for _, info in ipairs(all) do
    print(info.path, info.type, info.name)
end

Zwraca: table — posortowana tablica {path, type, name}


_:find(pattern) — wyszukiwanie wzorcem#

local douts = _:find("^CLU%.DOUT")
local remote = _:find("CLU[0-9]+%.DIM")

Parametry:

  • pattern (string) — wzorzec Lua (regex)

Zwraca: table — tablica {path, obj} pasujących wpisów

Przykłady wzorców:

_:find("%.DOUT$")           -- wszystkie DOUT
_:find("^CLU123%.")          -- obiekty konkretnego CLU
_:find("DIM[0-9]")           -- dimmery

_:info() — podsumowanie rejestru#

print(_:info())

Zwraca: string — sformatowane podsumowanie:

=== Object Registry ===

  CLU221000290: 15 objects
    - DOUT: 8
    - DIM: 4
    - ROLLER: 3

=== Total: 15 objects ===

_:toJSON() — eksport do JSON#

local json = _:toJSON()

Zwraca: string — tablica JSON ze wszystkimi obiektami:

[
  {
    "path": "CLU221000290.DOU1234",
    "type": "DOUT",
    "name": "Lampa Salon",
    "state": 1,
    "cluId": "CLU221000290",
    "objectId": "DOU1234",
    "mqttAccess": "full",
    "homekitAccess": "full"
  }
]

Rejestracja obiektów#

registerObject(path, obj)#

local switch = RemoteSwitch:new(clu, "DOU1234")
registerObject("CLU221000290.DOU1234", switch)

Parametry:

  • path (string) — pełna ścieżka obiektu
  • obj (table) — instancja obiektu

Zachowanie:

  • Zapisuje _registry[path] = obj
  • Jeśli obiekt ma _name → dodaje do _nameIndex[name] = path
  • Nadpisuje istniejący obiekt bez ostrzeżenia

RemoteGroup#

RemoteGroup zwracany przez byTag(), byTags() i find(). Umożliwia operacje masowe.

Iteracja i filtrowanie#

local group = _:byTag("lights")
local count = group:count()

group:each(function(obj, index)
    print(obj._name)
end)

local filtered = group:filter(function(obj)
    return obj._type == "DIMMER"
end)

Expose masowy#

group:expose("dimmer", {area = "Salon"})
group:unexpose()

Dynamiczne przekierowanie metod#

Każda nieznana metoda wywoływana na grupie jest przekazywana do każdego obiektu:

group:on()              -- obj:on() na każdym obiekcie
group:off()             -- obj:off() na każdym
group:setValue(50)       -- obj:setValue(50) na każdym

Zwraca self — chainable: group:on():setValue(100)


Właściwości obiektów#

Każdy obiekt w rejestrze dziedziczy z RemoteObject:

WłaściwośćTypOpis
_objIdstringID obiektu (np. "DOU1234")
_namestringNazwa wyświetlana
_typestringTyp obiektu ("DOUT", "DIMMER" itp.)
_lastStateanyBieżąca wartość stanu
_clutableReferencja do rodzica CLU
_tagstableTagi (klucz=tag, wartość=true)

Metody obiektów#

obj:addTag("tag1", "tag2")       -- dodaj tagi (chainable)
obj:removeTag("tag1")            -- usuń tag (chainable)
obj:hasTag("tag1")               -- sprawdź tag → bool
obj:getTags()                    -- pobierz tablicę tagów

obj:get(featureIndex)            -- odczyt feature
obj:set(featureIndex, value)     -- zapis feature
obj:getValue()                   -- stan (feature 0)
obj:setValue(value)              -- ustaw stan

obj:emit(eventName)              -- emituj event
obj:on(eventName, callback)      -- rejestruj listener
obj:off(eventName)               -- wyrejestruj
obj:add_event(eventName, cb)     -- rejestruj (legacy)
obj:onChange(callback)            -- subskrypcja zmian → unsubscribe fn

obj:getType()                    -- "DOUT", "DIN" itp.
obj:getName()                    -- nazwa obiektu
obj:getInfo()                    -- podsumowanie obiektu

StateBus — propagacja zmian#

Registry emituje zdarzenia przez StateBus:

state_changed#

StateBus:getShared():on("state_changed", function(data)
    print("Obiekt:", data.path)
    print("Nowa wartość:", data.value)
    print("Stara wartość:", data.oldValue)
    print("Typ:", data.type)
end)

Dane:

PoleTypOpis
pathstringPełna ścieżka obiektu
valueanyNowa wartość
oldValueanyPoprzednia wartość
typestringTyp obiektu
objtableInstancja obiektu

object_exposed / object_unexposed / object_updated#

StateBus:getShared():on("object_exposed", function(data)
    print("Exposed:", data.path, data.type, data.name)
end)

StateBus:getShared():on("object_unexposed", function(data)
    print("Unexposed:", data.path)
end)

Integracja z expose()#

Registry jest ściśle powiązany z systemem ExposedObjects — expose() API. Obiekty z rejestru można eksponować do MQTT/HomeKit na dwa sposoby:

Ręczne expose#

local lamp = _:get("CLU.DOUT1")
expose(lamp, "switch", {name = "Lampa Salon", area = "Salon"})

Masowe expose po tagu#

_:byTag("lights"):expose("light", {area = "Salon"})

Auto-expose#

exposeRegistry()   -- eksponuje wszystko z rejestru

Automatycznie eksponuje wszystkie obiekty z _registry do MQTT/HomeKit. Respektuje AccessControl i pomija obiekty już ręcznie wyeksponowane.

Priorytet:

  1. Ręczne expose() w user.lua — najwyższy
  2. AccessControl (access_control.yaml) — stosowany przez autoExpose
  3. exposeRegistry() — eksponuje resztę z domyślnymi ustawieniami

Pełna dokumentacja expose: ExposedObjects — expose() API