# Light
Ogólne sterowanie oświetleniem. Zawiera logikę wspólną dla wszystkich lamp, a komunikację deleguje do dołączonego bloku implementacji, który jako jedyny zna daną markę lub model.
# Bloki implementujące
| Nazwa | ID | Opis |
|---|---|---|
| TP-Link Tapo | tapo_light | Steruje żarówką lub taśmą LED TP-Link Tapo w sieci lokalnej przez szyfrowany protokół KLAP obecnego oprogramowania Tapo (L510, L530, L535, L610, L630, L900, L920 i podobne). Obsługa koloru i zakres bieli są odczytywane z urządzenia. |
Light
P
BR
CM
CT
H
S
P
BR
CM
CT
H
S
F
# Wejścia
| ID | Skrót | Nazwa | Typ | Domyślnie | Opis |
|---|---|---|---|---|---|
power | P | Zasilanie | BOOLEAN | false | Włącza światło przy stanie wysokim, wyłącza przy niskim |
brightness | BR | Jasność | NUMBER | 100 | Żądana jasność, od 1 do 100 % |
color_mode | CM | Tryb koloru | BOOLEAN | false | Stan niski - światło białe o żądanej temperaturze barwowej, stan wysoki - kolor określony odcieniem i nasyceniem. Lampa bez koloru pozostanie biała. |
color_temp | CT | Temperatura barwowa | NUMBER | 4000 | Żądana temperatura barwowa światła białego w kelwinach, zawężona do zakresu lampy. Ignorowana przez lampy bez regulacji bieli. |
hue | H | Odcień | NUMBER | 0 | Żądany odcień w trybie koloru, od 0 do 360 ° |
saturation | S | Nasycenie | NUMBER | 100 | Żądane nasycenie w trybie koloru, od 0 do 100 % |
# Wyjścia
| ID | Skrót | Nazwa | Typ | Domyślnie | Opis |
|---|---|---|---|---|---|
power | P | Zasilanie | BOOLEAN | false | Stan wysoki, gdy światło jest włączone. Odczytany z lampy, gdy implementacja udostępnia informację zwrotną, w przeciwnym razie stan zadany. |
brightness | BR | Jasność | NUMBER | 0 | Jasność lampy w % |
color_mode | CM | Tryb koloru | BOOLEAN | false | Stan wysoki, gdy lampa świeci kolorem, niski, gdy świeci światłem białym |
color_temp | CT | Temperatura barwowa | NUMBER | 0 | Temperatura barwowa światła białego w kelwinach. Wartość zadana, gdy lampa świeci kolorem lub jej nie raportuje. |
hue | H | Odcień | NUMBER | 0 | Odcień lampy w °. Wartość zadana, gdy lampa go nie raportuje. |
saturation | S | Nasycenie | NUMBER | 0 | Nasycenie lampy w %. Wartość zadana, gdy lampa go nie raportuje. |
fault | F | Awaria | NUMBER | 0 | 0 - brak awarii, -1 - brak komunikacji z lampą, powyżej 0 - kod błędu implementacji |
# Konfiguracja
| ID | Nazwa | Typ | Domyślnie | Jednostka | Opis |
|---|---|---|---|---|---|
features | Funkcje | ENUM | 3 | Co potrafi lampa, każdy poziom obejmuje poprzednie: włącz/wyłącz, jasność, temperatura barwowa bieli, kolor. Wejścia ponad poziom są ignorowane, a odpowiednie wyjścia mają -1 (tryb koloru niski). Szczegóły: Wartości: On/Off, Dimmable, Tunable white, Color |
# Stan
| ID | Nazwa | Typ | Domyślnie | Jednostka | Opis |
|---|---|---|---|---|---|
unit_power | Raportowane zasilanie | NUMBER | -1 | Stan zasilania raportowany przez blok implementacji: -1 nieznany, 0 wyłączone, 1 włączone | |
unit_brightness | Raportowana jasność | NUMBER | -1 | Jasność raportowana przez blok implementacji, -1 gdy nieznana | |
unit_color_mode | Raportowany tryb koloru | NUMBER | -1 | Tryb koloru raportowany przez blok implementacji: -1 nieznany, 0 biały, 1 kolor | |
unit_color_temp | Raportowana temperatura barwowa | NUMBER | -1 | Temperatura barwowa raportowana przez blok implementacji, -1 gdy nieznana | |
unit_hue | Raportowany odcień | NUMBER | -1 | Odcień raportowany przez blok implementacji, -1 gdy nieznany | |
unit_saturation | Raportowane nasycenie | NUMBER | -1 | Nasycenie raportowane przez blok implementacji, -1 gdy nieznane | |
unit_fault | Raportowana awaria | NUMBER | 0 | Awaria raportowana przez blok implementacji | |
invoke_rc | Wynik ostatniego wywołania implementacji | NUMBER | 0 | Wartość zwrócona przez ostatnie wywołanie implementacji, publikowana jako awaria, gdy lampa nie raportuje własnej | |
sent | Stan wysłany | BOOLEAN | false | Ustawione, gdy stan został przyjęty przez lampę co najmniej raz | |
sent_power | Wysłane zasilanie | BOOLEAN | false | Ostatni stan zasilania przyjęty przez lampę | |
sent_brightness | Wysłana jasność | NUMBER | 0 | Ostatnia jasność przyjęta przez lampę | |
sent_color_mode | Wysłany tryb koloru | BOOLEAN | false | Ostatni tryb koloru przyjęty przez lampę | |
sent_color_temp | Wysłana temperatura barwowa | NUMBER | 0 | Ostatnia temperatura barwowa przyjęta przez lampę | |
sent_hue | Wysłany odcień | NUMBER | 0 | Ostatni odcień przyjęty przez lampę | |
sent_saturation | Wysłane nasycenie | NUMBER | 0 | Ostatnie nasycenie przyjęte przez lampę |
# Kod źródłowy
Pokaż kod Volang
// Light - abstract block.
//
// Turns the input channels into one desired light state and hands it to the
// attached implementation (driver), the only part that knows how to reach a
// particular lamp (Wi-Fi bulb, DALI, Zigbee, ...).
//
// Value encodings, shared by the inputs, the outputs and the driver call:
// brightness 1..100 %
// color_mode false white light at color_temp, true color at hue/saturation
// color_temp K, the driver narrows it to what the lamp can do
// hue 0..360 °
// saturation 0..100 %
// fault 0 none, -1 lamp unreachable, > 0 driver specific error code
// The features config tells what the lamp can do, each level including the
// previous ones:
// 0 on/off, 1 dimmable (brightness), 2 tunable white (color_temp),
// 3 color (color_mode, hue, saturation)
// The values beyond it are passed to the driver and published as -1, with
// color_mode low. A lamp that still cannot do what was asked for falls back
// to its closest equivalent - one without color stays white, one without a
// color temperature keeps its own - and that mapping belongs to the driver.
//
// The driver must declare one function:
//
// light_apply(power, brightness, color_mode, color_temp, hue, saturation)
// Pushes the complete desired state, called whenever a value changes.
// A value of -1 means the lamp keeps its own setting.
// It only has to accept the work, not finish it: a driver on the network
// returns as soon as the request is out, and one still busy with an
// earlier exchange keeps the state and sends it once that is over.
// Returns 0 when accepted, otherwise an error code that is published on
// the fault output.
//
// Whether and how often the lamp is polled for its status is up to the
// driver, which can be scheduled on its own. Either way it reports back through
// this block's state, then returns non-zero from the run that stored the
// readings, so the runtime calls std::on_driver_update here:
// unit_power -1 unknown, 0 off, 1 on
// unit_brightness -1 unknown, otherwise %
// unit_color_mode -1 unknown, 0 white, 1 color
// unit_color_temp -1 unknown, otherwise K
// unit_hue -1 unknown, otherwise °
// unit_saturation -1 unknown, otherwise %
// unit_fault the fault value to publish
// Whatever is left unknown is published as the value this block commanded, so
// a lamp without feedback simply never touches these.
fn clamp_int(value, lo, hi) {
v = math::int(math::round(value))
if (v < lo) {
return lo
}
if (v > hi) {
return hi
}
return v
}
fn publish(power, brightness, color_mode, color_temp, hue, saturation) {
features = config::get("features")
unit_power = state::get("unit_power")
if (unit_power >= 0) {
power = unit_power != 0
}
unit_brightness = state::get("unit_brightness")
if (unit_brightness >= 0 and features >= 1) {
brightness = unit_brightness
}
unit_color_mode = state::get("unit_color_mode")
if (unit_color_mode >= 0 and features >= 3) {
color_mode = unit_color_mode != 0
}
unit_color_temp = state::get("unit_color_temp")
if (unit_color_temp >= 0 and features >= 2) {
color_temp = unit_color_temp
}
unit_hue = state::get("unit_hue")
if (unit_hue >= 0 and features >= 3) {
hue = unit_hue
}
unit_saturation = state::get("unit_saturation")
if (unit_saturation >= 0 and features >= 3) {
saturation = unit_saturation
}
fault = state::get("unit_fault")
if (fault == 0) {
fault = state::get("invoke_rc")
}
output::set("power", power)
output::set("brightness", brightness)
output::set("color_mode", color_mode)
output::set("color_temp", color_temp)
output::set("hue", hue)
output::set("saturation", saturation)
output::set("fault", fault)
}
fn changed(power, brightness, color_mode, color_temp, hue, saturation) {
if (!state::get("sent")) {
return true
}
if (state::get("sent_power") != power) {
return true
}
if (state::get("sent_brightness") != brightness) {
return true
}
if (state::get("sent_color_mode") != color_mode) {
return true
}
if (state::get("sent_color_temp") != color_temp) {
return true
}
if (state::get("sent_hue") != hue) {
return true
}
if (state::get("sent_saturation") != saturation) {
return true
}
return false
}
// The last readings describe the lamp before a command, so they must not mask
// what was just asked for; the read that follows fills them in again.
fn forget_readings() {
state::set("unit_power", -1)
state::set("unit_brightness", -1)
state::set("unit_color_mode", -1)
state::set("unit_color_temp", -1)
state::set("unit_hue", -1)
state::set("unit_saturation", -1)
}
fn remember(power, brightness, color_mode, color_temp, hue, saturation) {
state::set("sent_power", power)
state::set("sent_brightness", brightness)
state::set("sent_color_mode", color_mode)
state::set("sent_color_temp", color_temp)
state::set("sent_hue", hue)
state::set("sent_saturation", saturation)
state::set("sent", true)
}
// Called by the runtime after the driver stored fresh readings. The commanded
// values are only a fallback for whatever the lamp did not report.
extern fn std::on_driver_update() {
power = state::get("sent_power")
brightness = state::get("sent_brightness")
color_mode = state::get("sent_color_mode")
color_temp = state::get("sent_color_temp")
hue = state::get("sent_hue")
saturation = state::get("sent_saturation")
publish(power, brightness, color_mode, color_temp, hue, saturation)
}
power = input::get("power")
brightness = clamp_int(input::get("brightness"), 1, 100)
color_mode = input::get("color_mode")
color_temp = clamp_int(input::get("color_temp"), 1000, 10000)
hue = clamp_int(input::get("hue"), 0, 360)
saturation = clamp_int(input::get("saturation"), 0, 100)
features = config::get("features")
if (features < 1) {
brightness = -1
}
if (features < 2) {
color_temp = -1
}
if (features < 3) {
color_mode = false
hue = -1
saturation = -1
}
if (changed(power, brightness, color_mode, color_temp, hue, saturation)) {
// Report the commanded state right away, so the outputs stay meaningful
// even when the driver call below fails or no driver is attached at all.
publish(power, brightness, color_mode, color_temp, hue, saturation)
rc = std::invoke("light_apply", power, brightness, color_mode, color_temp, hue, saturation)
state::set("invoke_rc", rc)
if (rc == 0) {
remember(power, brightness, color_mode, color_temp, hue, saturation)
forget_readings()
}
}
publish(power, brightness, color_mode, color_temp, hue, saturation)