volangstdlibreferencjafunkcje

# Biblioteka standardowa

Biblioteka standardowa Volang zapewnia kompleksowy zestaw wbudowanych funkcji niezbędnych do modyfikowania tekstu, wykonywania operacji matematycznych i innych typowych operacji. Funkcje te są dostępne globalnie w każdym skrypcie.

# Operacje wejściowe

Ta sekcja opisuje funkcje do odczytu danych wejściowych w ramach bloku logicznego. Każdy blok logiczny może definiować jeden lub więcej kanałów wejściowych. Gdy wartość wejściowa się zmieni, skrypt bloku zostaje wykonany. Funkcje te pozwalają skryptowi określić, które wejście wywołało wykonanie, oraz odczytać bieżące wartości wszystkich wejść.

# input::channel

Zwraca identyfikator kanału wejściowego, który wywołał bieżące wykonanie skryptu. Gdy blok posiada wiele wejść, ta funkcja jest niezbędna do określenia, które wejście spowodowało uruchomienie bloku, umożliwiając obsługę każdego wejścia w inny sposób.

Parametry:

  • Brak.

Zwraca:

  • Łańcuch zawierający identyfikator wejścia, które wywołało wykonanie.

Przykład:

channel = input::channel()

if (channel == "input") {
    // Główne wejście przełączające zostało wyzwolone
    ...
} else if (channel == "on") {
    // Dedykowane wejście "on" zostało wyzwolone
    ...
} else if (channel == "off") {
    // Dedykowane wejście "off" zostało wyzwolone
    ...
}

# input::value

Zwraca wartość wejścia, które wywołało bieżące wykonanie skryptu. Typ zwracany zależy od zdefiniowanego typu wejścia (boolean, number lub string). Użyj tej funkcji razem z input::channel(), aby określić zarówno które wejście się zmieniło, jak i jaka jest jego nowa wartość.

Parametry:

  • Brak.

Zwraca:

  • Bieżącą wartość wyzwalającego wejścia. Typ zależy od definicji wejścia (boolean, number lub string).

Przykład:

channel = input::channel()
value = input::value()

// Reaguj na zbocze narastające na wejściu boolowskim
if (channel == "input" and value) {
    output::toggle("output")
}

# input::get

Pobiera ostatnią znaną wartość określonego wejścia po jego identyfikatorze. W przeciwieństwie do input::value(), która zwraca jedynie wartość wejścia wywołującego bieżące wykonanie, ta funkcja może odczytać zapisaną wartość dowolnego wejścia w dowolnym momencie.

Parametry:

  • id (string): Identyfikator wejścia do odczytu.

Zwraca:

  • Ostatnią znaną wartość określonego wejścia. Typ zależy od definicji wejścia (boolean, number lub string).

Przykład:

// Odczytaj bieżącą temperaturę z wejścia
current_temp = input::get("value")

// Użyj wartości w logice sterowania
if (current_temp > 25.0) {
    output::set("cooling", true)
}

# Operacje wyjściowe

Ta sekcja opisuje funkcje do sterowania wyjściami bloku logicznego. Każdy blok może definiować jedno lub więcej wyjść, które przekazują wartości do innych podłączonych bloków.

# output::get

Pobiera bieżącą wartość określonego wyjścia po jego identyfikatorze. Jest to przydatne do odczytu bieżącego stanu wyjścia przed podjęciem decyzji o jego zmianie.

Parametry:

  • id (string): Identyfikator wyjścia do odczytu.

Zwraca:

  • Bieżącą wartość określonego wyjścia. Typ zależy od definicji wyjścia (boolean, number lub string).

Przykład:

// Sprawdź bieżący stan wyjścia przed przełączeniem
prev = output::get("output")
if (prev) {
    std::print("Wyjście jest aktualnie WŁĄCZONE, wyłączam")
}
output::set("output", !prev)

# output::set

Ustawia wartość określonego wyjścia po jego identyfikatorze. Typ wartości musi odpowiadać typowi zdefiniowanemu dla tego wyjścia (boolean, number lub string). Ustawienie wyjścia propaguje nową wartość do wszelkich podłączonych bloków.

Parametry:

  • id (string): Identyfikator wyjścia do ustawienia.
  • value: Nowa wartość do przypisania. Musi odpowiadać zdefiniowanemu typowi wyjścia.

Zwraca:

  • Nic.

Przykład:

// Ustaw wyjście boolowskie
output::set("output", true)

// Ustaw wyjście numeryczne na podstawie obliczeń
midpoint = config::get("midpoint")
hysteresis = config::get("hysteresis")
value = input::get("value")

if (value >= midpoint + hysteresis) {
    output::set("output", true)
} else if (value <= midpoint - hysteresis) {
    output::set("output", false)
}

# output::toggle

Przełącza wyjście boolowskie, odwracając jego bieżącą wartość. Jeśli wyjście jest obecnie true, staje się false i odwrotnie. Ta funkcja działa tylko z wyjściami typu boolean.

Parametry:

  • id (string): Identyfikator wyjścia boolowskiego do przełączenia.

Zwraca:

  • Nic.

Przykład:

channel = input::channel()
value = input::value()

// Przełącz wyjście na zbocze narastające wejścia
if (channel == "input") {
    last_state = state::get("last_input_state")
    if (value and !last_state) {
        output::toggle("output")
    }
    state::set("last_input_state", value)
}

# Operacje na stanie

Ta sekcja opisuje funkcje do zarządzania trwałym stanem w ramach bloku logicznego. Zmienne stanu zachowują swoje wartości pomiędzy wykonaniami skryptu, co czyni je niezbędnymi do śledzenia warunków w czasie, takich jak detekcja zboczy, liczniki czy informacje czasowe. Dostępne zmienne stanu i ich typy są zdefiniowane w deskryptorze bloku.

# state::get

Pobiera bieżącą wartość trwałej zmiennej stanu po jej identyfikatorze.

Parametry:

  • id (string): Identyfikator zmiennej stanu do odczytu.

Zwraca:

  • Bieżącą wartość zmiennej stanu. Typ zależy od definicji zmiennej stanu (boolean, number lub string).

Przykład:

// Użyj stanu do wykrycia zbocza narastającego (przejście z false na true)
value = input::value()
last_state = state::get("last_input_state")

if (value and !last_state) {
    // Wykryto zbocze narastające - podejmij działanie
    output::toggle("output")
}

state::set("last_input_state", value)

# state::set

Zapisuje wartość w trwałej zmiennej stanu po jej identyfikatorze. Wartość jest zachowywana pomiędzy wykonaniami skryptu, umożliwiając blokowi zapamiętywanie informacji między wieloma zdarzeniami wejściowymi. Typ wartości musi odpowiadać typowi zdefiniowanemu dla tej zmiennej stanu.

Parametry:

  • id (string): Identyfikator zmiennej stanu do aktualizacji.
  • value: Nowa wartość do zapisania. Musi odpowiadać zdefiniowanemu typowi zmiennej stanu.

Zwraca:

  • Nic.

Przykład:

// Śledź znacznik czasu ostatniej zmiany wejścia
channel = input::channel()
value = input::value()

if (channel == "input") {
    state::set("last_change_time", time::now())

    // Oblicz, jak długo wejście było w poprzednim stanie
    elapsed = time::now() - state::get("last_change_time")
    if (elapsed > 60) {
        std::print("Wejście było stabilne przez ponad minutę")
    }
}

# Operacje konfiguracyjne

Ta sekcja opisuje funkcje do odczytu parametrów konfiguracyjnych bloku. Wartości konfiguracyjne są ustawiane przez użytkownika w Voldeno Studio i są tylko do odczytu z poziomu skryptu. Pozwalają na dostosowanie bloków bez modyfikowania kodu — na przykład ustawianie progów, opóźnień czy trybów pracy.

# config::get

Pobiera wartość parametru konfiguracyjnego po jego identyfikatorze. Parametry konfiguracyjne są zdefiniowane w deskryptorze bloku, a ich wartości są ustawiane przez użytkownika w Voldeno Studio. Skrypt może jedynie odczytywać te wartości, nie może ich modyfikować.

Parametry:

  • id (string): Identyfikator parametru konfiguracyjnego do odczytu.

Zwraca:

  • Wartość parametru konfiguracyjnego. Typ zależy od definicji parametru (number, string lub enum). Parametry typu enum zwracają swój indeks numeryczny liczony od zera.

Przykład:

// Odczytaj konfigurację opóźnienia w milisekundach
delay_on_ms = config::get("delay_on_ms")
delay_off_ms = config::get("delay_off_ms")

// Użyj konfiguracji typu enum do wyboru trybu zachowania
mode = config::get("mode") // Zwraca 0, 1, 2... w zależności od wybranej opcji

if (mode == 0) {
    // Logika pierwszego trybu
    ...
} else if (mode == 1) {
    // Logika drugiego trybu
    ...
}

// Odczytaj próg numeryczny z konfiguracji
scale = config::get("scale")
offset = config::get("offset")
result = input::value() * scale + offset
output::set("value", result)

# Operacje callbacków

Ta sekcja opisuje funkcje do planowania opóźnionych wywołań funkcji. Volang jest językiem nieblokującym i nie udostępnia funkcji sleep. Zamiast tego callbacki zapewniają mechanizm logiki czasowej poprzez planowanie wywołania zdefiniowanej przez użytkownika funkcji po określonym opóźnieniu.

Jest to niezbędne do implementacji zachowań takich jak opóźnienia, impulsy czasowe, sekwencje sterowania silnikami czy dowolna logika wymagająca działania po upływie określonego czasu. Callback może przekazać argumenty do wywoływanej funkcji, a funkcja może planować kolejne callbacki, tworząc wielokrokowe sekwencje.

Tylko jeden callback może być aktywny w danym momencie dla jednego bloku. Zaplanowanie nowego callbacka, gdy jeden jest już oczekujący, wymaga najpierw anulowania istniejącego za pomocą callback::clear().

# callback::set

Planuje opóźnione wywołanie zdefiniowanej przez użytkownika funkcji extern po określonym opóźnieniu w milisekundach. Funkcja jest identyfikowana przez swoją nazwę jako łańcuch. Dodatkowe argumenty mogą być przekazane i zostaną dostarczone do funkcji callback jako jej parametry.

Funkcja docelowa musi być zadeklarowana z użyciem składni extern fn w skrypcie. Gdy opóźnienie upłynie, system wywołuje tę funkcję z podanymi argumentami.

Parametry:

  • delay_ms (integer): Opóźnienie w milisekundach przed wywołaniem funkcji.
  • function_name (string): Nazwa funkcji extern fn do wywołania.
  • ...args (opcjonalne): Dodatkowe argumenty do przekazania do funkcji callback. Można przekazać zero lub więcej wartości dowolnego typu.

Zwraca:

  • Nic.

Przykład:

// Zdefiniuj prosty handler callbacka
extern fn onTimeout() {
    output::set("output", true)
}

// Zaplanuj callback do wywołania po konfigurowalnym opóźnieniu
delay_ms = config::get("delay_ms")
callback::set(delay_ms, "onTimeout")

Przykład — przekazywanie argumentów:

// Callback łańcuchowy przechodzący do następnego kroku
extern fn onSequence(step) {
    if (step == 1) {
        output::set("output", true)
        // Zaplanuj krok 2 po czasie trwania impulsu
        pulse_ms = config::get("pulse_ms")
        callback::set(pulse_ms, "onSequence", 2)
        return
    }
    if (step == 2) {
        output::set("output", false)
        return
    }
}

// Rozpocznij sekwencję po początkowym opóźnieniu
callback::set(1000, "onSequence", 1)

# callback::clear

Anuluje aktualnie zaplanowany callback dla bloku. Powinno być wywoływane przed zaplanowaniem nowego callbacka lub gdy oczekujące działanie nie jest już potrzebne (np. wejście zmieniło się przed upłynięciem opóźnienia).

Parametry:

  • Brak.

Zwraca:

  • Nic.

Przykład:

extern fn onCallback(value) {
    if (value == 1) {
        output::set("output", true)
    } else if (value == 2) {
        output::set("output", false)
    }
}

channel = input::channel()
value = input::value()

if (channel == "input") {
    last = state::get("last_input_state")
    if (value != last) {
        state::set("last_input_state", value)

        // Zawsze anuluj poprzedni callback przed zaplanowaniem nowego
        callback::clear()

        if (value) {
            delay_ms = config::get("delay_on_ms")
            if (delay_ms > 0) {
                callback::set(delay_ms, "onCallback", 1)
            } else {
                output::set("output", true)
            }
        } else {
            delay_ms = config::get("delay_off_ms")
            if (delay_ms > 0) {
                callback::set(delay_ms, "onCallback", 2)
            } else {
                output::set("output", false)
            }
        }
    }
}

# Operacje na łańcuchach znaków

Ta sekcja opisuje funkcje służące do manipulacji łańcuchami znaków.

# str::len

Oblicza liczbę znaków w podanym łańcuchu.

Parametry:

  • text (string): Łańcuch wejściowy do zmierzenia.

Zwraca:

  • Wartość całkowitą reprezentującą liczbę znaków w łańcuchu.

Przykład:

// Sprawdź, czy kod PIN użytkownika ma wymaganą długość
user_pin = "1234"
if (str::len(user_pin) == 4) {
    ...
}

# str::trim

Usuwa wszystkie wiodące i końcowe znaki białe (spacje, tabulatory, znaki nowej linii) z łańcucha. Jest to niezbędne do czyszczenia danych wejściowych użytkownika lub parsowania poleceń otrzymanych z systemów zewnętrznych, gdzie mogą wystąpić dodatkowe odstępy.

Parametry:

  • text (string): Łańcuch wejściowy do przycięcia.

Zwraca:

  • Nowy tekst zawierający tekst bez otaczających znaków białych.

Przykład:

// Wyczyść polecenie otrzymane z modułu zewnętrznego
input = "  START  "
command = str::trim(input)

// Teraz łańcuch to "START" i może być bezpiecznie porównany
if (command == "START") {
    ....
}

# str::concat

Łączy (konkatenuje) dwa lub więcej łańcuchów w jeden łańcuch. Ta funkcja jest wariadyczna, co oznacza, że akceptuje zmienną liczbę argumentów, umożliwiając dynamiczne budowanie złożonych komunikatów lub poleceń.

Parametry:

  • ...strings: Sekwencja argumentów łańcuchowych do połączenia. Możesz przekazać dowolną liczbę argumentów, oddzielonych przecinkami. Można również podać pojedynczy argument — w takim przypadku funkcja zwraca sam ten argument.

Zwraca:

  • Nowy łańcuch składający się ze wszystkich łańcuchów wejściowych połączonych w kolejności.

Przykład:

room = "Salon"
temp = "22.5"

// Zbuduj pełny komunikat o stanie używając wielu argumentów
message = str::concat("Status: ", room, " ma obecnie ", temp, "°C")

// Wynik: "Status: Salon ma obecnie 22.5°C"

# str::count

Zlicza liczbę nienakładających się wystąpień podłańcucha w łańcuchu. Opcjonalnie wyszukiwanie może być ograniczone do określonego zakresu w łańcuchu za pomocą argumentów pozycji start i end.

Parametry:

  • text (string): Łańcuch, w którym ma być wykonane wyszukiwanie.
  • substring (string): Podłańcuch, którego wystąpienia mają być zliczone.
  • start (integer, opcjonalne): Pozycja, od której ma rozpocząć się wyszukiwanie. Domyślnie 0.
  • end (integer, opcjonalne): Pozycja, na której ma zakończyć się wyszukiwanie (wyłącznie). Domyślnie koniec łańcucha.

Zwraca:

  • Wartość całkowitą reprezentującą liczbę nienakładających się wystąpień podłańcucha.

Przykład:

// Zlicz wszystkie wystąpienia słowa
text = "I love apples, apple are my favorite fruit"
count = str::count(text, "apple") // Zwraca 2

// Zlicz wystąpienia w zakresie
data = "abcabcabc"
count = str::count(data, "abc", 1)    // Zwraca 2 (pomija pierwsze "abc")
count = str::count(data, "abc", 1, 7) // Zwraca 1

// Pusty podłańcuch zwraca długość + 1
count = str::count("hello", "") // Zwraca 6

// Nienakładające się: "aaaa" zawiera 2 nienakładające się "aa"
count = str::count("aaaa", "aa") // Zwraca 2

# str::replace

Zastępuje wystąpienia podłańcucha w łańcuchu nowym podłańcuchem. Domyślnie zastępowane są wszystkie wystąpienia. Opcjonalny parametr count ogranicza liczbę zamian wykonywanych od lewej do prawej.

Parametry:

  • text (string): Oryginalny łańcuch.
  • old (string): Podłańcuch do zastąpienia.
  • new (string): Podłańcuch, którym ma być zastąpiony.
  • count (integer, opcjonalne): Maksymalna liczba zamian. Jeśli pominięto, zastępowane są wszystkie wystąpienia.

Zwraca:

  • Nowy łańcuch z zastosowanymi zamianami.

Przykład:

// Zastąp wszystkie wystąpienia
result = str::replace("one one was a horse", "one", "three")
// Zwraca "three three was a horse"

// Zastąp tylko pierwsze wystąpienie
result = str::replace("one one was a horse", "one", "three", 1)
// Zwraca "three one was a horse"

// Usuwanie przez zastąpienie pustym łańcuchem
result = str::replace("hello", "l", "") // Zwraca "heo"

// Pusty old wstawia między każdy znak
result = str::replace("abc", "", "-") // Zwraca "-a-b-c-"

# str::number

Parsuje argument łańcuchowy i konwertuje go na wartość numeryczną. Funkcja automatycznie wykrywa format: jeśli łańcuch zawiera kropkę dziesiętną, zwraca liczbę zmiennoprzecinkową, w przeciwnym razie zwraca liczbę całkowitą.

Parametry:

  • text: Łańcuch zawierający reprezentację liczby.

Zwraca:

  • Wartość numeryczną, całkowitą lub zmiennoprzecinkową, w zależności od formatu wejściowego.

Przykład:

// Przypadek 1: Parsowanie liczby całkowitej (np. poziom jasności)
brightness = str::number("80") // Zwraca Integer 80

// Przypadek 2: Parsowanie liczby zmiennoprzecinkowej (np. temperatura)
temp_str = "21.5"
threshold = str::number(temp_str) // Zwraca Float 21.5
current_temp = 22

// Użycie przekonwertowanej wartości w logice
if (current_temp > threshold) {
    ...
}

# str::fmt

Konstruuje sformatowany łańcuch poprzez zastępowanie symboli zastępczych {} w szablonie łańcuchowym reprezentacją tekstową podanych argumentów. Akceptuje zmienną liczbę argumentów różnych typów (łańcuchy, wartości numeryczne i logiczne) i automatycznie konwertuje je na tekst przed wstawieniem. Zamiana jest pozycyjna: pierwszy {} jest zastępowany pierwszym argumentem, drugi {} drugim itd.

Parametry:

  • template: Łańcuch formatujący zawierający symbole zastępcze w nawiasach klamrowych {}.
  • ...args: Sekwencja wartości do podstawienia w miejsca symboli zastępczych. Obsługiwane typy to liczby, łańcuchy i literały logiczne (true/false).

Zwraca:

  • Nowy łańcuch ze wszystkimi symbolami zastępczymi zastąpionymi odpowiednimi wartościami.

Przykład:

sensorName = "Kuchnia_Glowna"
temp = 22.5
isActive = true

// Sformatuj złożony komunikat logu bez ręcznej konkatenacji
log = str::fmt("Czujnik {} status: Aktywny={}, Wartość={}°C", sensorName, isActive, temp)

// Wynik: "Czujnik Kuchnia_Glowna status: Aktywny=true, Wartość=22.5°C"

# str::split

Inicjalizuje operację dzielenia łańcucha i tworzy stan iteratora. Ta funkcja nie wykonuje faktycznego dzielenia natychmiast. Zamiast tego zwraca nieprzezroczysty obiekt handle, który zawiera bieżącą pozycję i logikę wymaganą do przechodzenia przez łańcuch. Ten obiekt musi być przekazany do str::split_next lub str::split_has_next, aby pobierać rzeczywiste podłańcuchy jeden po drugim.

Parametry:

  • text: Łańcuch źródłowy do podzielenia.
  • separator: Łańcuch separatora, który oznacza granice między fragmentami.

Zwraca:

  • Nieprzezroczysty uchwyt reprezentujący aktywną sesję dzielenia. Nie należy modyfikować tego obiektu bezpośrednio.

Przykład:

rawData = "sensor1;25.5;active"

// Zainicjalizuj splitter. 'iterator' teraz przechowuje stan.
iterator = str::split(rawData, ";")

// Iterator jest teraz gotowy do użycia przez split_next...

# str::split_has_next

Sprawdza, czy są jeszcze podłańcuchy oczekujące na pobranie z bieżącej sesji dzielenia. Ta funkcja sprawdza nieprzezroczysty obiekt state utworzony przez str::split. Nie modyfikuje stanu ani nie przesuwa pozycji iteratora; jedynie weryfikuje dostępność. Jest powszechnie używana jako warunek w pętli while do iterowania przez wszystkie części łańcucha.

Parametry:

  • state: Nieprzezroczysty uchwyt zwrócony przez str::split.

Zwraca:

  • true, jeśli dostępny jest co najmniej jeden kolejny podłańcuch; w przeciwnym razie zwraca false.

Przykład:

data = "CZERWONY,ZIELONY,NIEBIESKI"
iterator = str::split(data, ",")

// Pętla dopóki są pozostałe tokeny
while (str::split_has_next(iterator)) {
    ...
    // Bezpieczne wywołanie split_next() tutaj
    // color = str::split_next(iterator) 
}

# str::split_next

Wyodrębnia i zwraca następny podłańcuch z sekwencji dzielenia oraz przesuwa iterator na następną pozycję. Ta funkcja zużywa bieżący segment łańcucha identyfikowany przez nieprzezroczysty state. Jest zaprojektowana do sekwencyjnego wywoływania, aż wszystkie części łańcucha zostaną przetworzone.

Parametry:

  • state: Nieprzezroczysty uchwyt zwrócony przez str::split.

Zwraca:

  • Następny segment oryginalnego tekstu.
Warning

Zaleca się zweryfikowanie dostępności za pomocą str::split_has_next(state) przed wywołaniem tej funkcji, aby zapewnić bezpieczną iterację.

Przykład:

// Scenariusz: Parsowanie łańcucha polecenia "SET_COLOR;255;0;0"
commandRaw = "SET_COLOR;255;0;0"
iter = str::split(commandRaw, ";")

// Znamy format, więc możemy wyodrębnić części ręcznie
if (str::split_has_next(iter)) {
    cmd = str::split_next(iter)   // "SET_COLOR"
    r = str::split_next(iter)     // "255"
    g = str::split_next(iter)     // "0"
    b = str::split_next(iter)     // "0"
    ...
}

# Operacje na tablicach

Ta sekcja opisuje funkcje do tworzenia i manipulowania tablicami.

# array::new

Tworzy nową tablicę zainicjalizowaną podanymi wartościami. Ta funkcja jest wariadyczna, co oznacza, że akceptuje zmienną liczbę argumentów dowolnego typu. Wywołana bez argumentów tworzy pustą tablicę. Tablice mogą przechowywać różne typy, a ich rozmiar może być dynamicznie zmieniany za pomocą innych funkcji tablicowych.

Parametry:

  • ...values (opcjonalne): Sekwencja wartości do zainicjalizowania tablicy. Możesz przekazać zero lub więcej argumentów dowolnego typu (liczby, łańcuchy, wartości logiczne, a nawet inne tablice). Jeśli nie podano żadnych argumentów, tworzona jest pusta tablica.

Zwraca:

  • Nieprzezroczysty uchwyt reprezentujący utworzoną tablicę. Ten uchwyt powinien być przekazywany do innych funkcji tablicowych (takich jak array::put_at, array::get_at, array::len) w celu manipulowania zawartością tablicy.

Przykład:

// Utwórz pustą tablicę
empty = array::new()

// Utwórz tablicę z początkowymi wartościami numerycznymi
temperatures = array::new(21.5, 22.0, 19.8, 23.1)

// Utwórz tablicę z różnymi typami
config = array::new("sensor1", 100, true)

// Utwórz tablicę z wartościami łańcuchowymi dla nazw pokojów
rooms = array::new("Salon", "Kuchnia", "Sypialnia", "Łazienka")

// Tablice mogą być używane do zbierania odczytów czujników w czasie
readings = array::new()
// Później: array::push(readings, current_value)

# array::len

Zwraca liczbę elementów aktualnie przechowywanych w tablicy. Ta funkcja jest przydatna do sprawdzania, czy tablica jest pusta, iterowania po wszystkich elementach lub walidacji rozmiaru tablicy przed dostępem do określonych indeksów.

Parametry:

  • arr: Nieprzezroczysty uchwyt tablicy zwrócony przez array::new.

Zwraca:

  • Wartość całkowitą reprezentującą liczbę elementów w tablicy.

Przykład:

// Sprawdź rozmiar tablicy
temps = array::new(21.5, 22.0, 19.8)
count = array::len(temps) // Zwraca 3

// Sprawdź, czy tablica jest pusta
data = array::new()
if (array::len(data) == 0) {
    std::print("Brak zebranych danych")
}

// Użyj długości do granic iteracji
sensors = array::new("temp1", "temp2", "humidity")
i = 0
while (i < array::len(sensors)) {
    // Przetwórz każdy czujnik...
    i = i + 1
}

# array::get_at

Pobiera wartość przechowywaną pod określonym indeksem w tablicy. Indeksy tablicy są liczone od zera, co oznacza, że pierwszy element znajduje się pod indeksem 0, drugi pod indeksem 1 itd.

Parametry:

  • arr: Nieprzezroczysty uchwyt tablicy zwrócony przez array::new.
  • index: Pozycja elementu do pobrania, liczona od zera.

Zwraca:

  • Wartość przechowywaną pod określonym indeksem. Typ zwracany zależy od tego, co zostało zapisane na tej pozycji.
Warning

Musisz upewnić się, że indeks mieści się w prawidłowych granicach (tj. 0 <= index < array::len(arr)) przed wywołaniem tej funkcji. Próba dostępu do indeksu, który nie istnieje, zakończy się błędem wykonania programu, co może skutkować niezdefiniowanym zachowaniem. Zawsze najpierw zwaliduj indeks używając array::len().

Przykład:

temps = array::new(21.5, 22.0, 19.8, 23.1)

// Bezpieczny dostęp: najpierw sprawdź granice
index = 2
if (index < array::len(temps)) {
    value = array::get_at(temps, index) // Zwraca 19.8
    std::print(str::fmt("Temperatura pod indeksem {}: {}°C", index, value))
}

// Bezpieczna iteracja po wszystkich elementach
i = 0
while (i < array::len(temps)) {
    temp = array::get_at(temps, i)
    if (temp > 22.0) {
        std::print(str::fmt("Wykryto wysoką temperaturę: {}°C", temp))
    }
    i = i + 1
}

// NIEBEZPIECZNE: Nigdy nie rób tego bez sprawdzania granic!
// value = array::get_at(temps, 10) // Niezdefiniowane zachowanie - może spowodować awarię!

# array::put_at

Zapisuje wartość pod określonym indeksem w tablicy, zastępując istniejącą wartość na tej pozycji. Indeksy tablicy są liczone od zera, co oznacza, że pierwszy element znajduje się pod indeksem 0, drugi pod indeksem 1 itd. Ta funkcja modyfikuje tablicę w miejscu i nie zwraca wartości.

Parametry:

  • arr: Nieprzezroczysty uchwyt tablicy zwrócony przez array::new.
  • index: Pozycja liczona od zera, gdzie wartość powinna zostać zapisana.
  • value: Wartość do zapisania pod określonym indeksem. Typ wartości musi być zgodny z typem elementu już przechowywanego na tej pozycji w tablicy.

Zwraca:

  • Nic.
Warning

Musisz upewnić się, że indeks mieści się w prawidłowych granicach (tj. 0 <= index < array::len(arr)) przed wywołaniem tej funkcji. Próba zapisu do indeksu, który nie istnieje, zakończy się błędem wykonania programu, co może skutkować niezdefiniowanym zachowaniem. Zawsze najpierw zwaliduj indeks używając array::len().

Przykład:

// Utwórz tablicę z początkowymi wartościami
temps = array::new(21.5, 22.0, 19.8, 23.1)

// Bezpieczna aktualizacja: najpierw sprawdź granice
index = 1
if (index < array::len(temps)) {
    array::put_at(temps, index, 25.0) // Zastąp 22.0 przez 25.0
}

// Aktualizuj wszystkie wartości w pętli
i = 0
while (i < array::len(temps)) {
    current = array::get_at(temps, i)
    // Zastosuj współczynnik korekcji
    array::put_at(temps, i, current + 0.5)
    i = i + 1
}

// Aktualizuj określone elementy w tablicy łańcuchów
sensors = array::new("sensor1", "sensor2", "sensor3")
array::put_at(sensors, 0, "temp1")
array::put_at(sensors, 1, "temp2")
array::put_at(sensors, 2, "humidity")

// NIEBEZPIECZNE: Nigdy nie rób tego bez sprawdzania granic!
// array::put_at(temps, 10, 99.9) // Niezdefiniowane zachowanie - może spowodować awarię!

# array::append

Dodaje wartość na koniec tablicy, zwiększając jej rozmiar o jeden. Ta funkcja jest przydatna do dynamicznego budowania tablic, gdy końcowy rozmiar nie jest znany z góry.

Parametry:

  • arr: Nieprzezroczysty uchwyt tablicy zwrócony przez array::new.
  • value: Wartość do dodania na końcu tablicy.

Zwraca:

  • Nic.

Przykład:

// Buduj tablicę dynamicznie dodając wartości
temps = array::new(21.5)
array::append(temps, 22.0)
array::append(temps, 19.8)
array::append(temps, 23.1)
// temps teraz zawiera: [21.5, 22.0, 19.8, 23.1]

// Zbieraj odczyty czujników w czasie
readings = array::new(0.0) // Zainicjalizuj pierwszym odczytem
array::append(readings, 0.5)
array::append(readings, 1.2)

// Sprawdź nowy rozmiar
count = array::len(readings) // Zwraca 3

// Dodawaj w pętli (np. zbieranie 5 odczytów)
data = array::new(100)
i = 0
while (i < 4) {
    array::append(data, 100 + i)
    i = i + 1
}
// data teraz zawiera: [100, 100, 101, 102, 103]

# array::clear

Usuwa wszystkie elementy z tablicy, pozostawiając ją pustą. Po wywołaniu tej funkcji array::len(arr) zwróci 0. Ta funkcja jest przydatna do ponownego wykorzystania tablicy bez tworzenia nowej.

Parametry:

  • arr: Nieprzezroczysty uchwyt tablicy zwrócony przez array::new.

Zwraca:

  • Nic.

Przykład:

// Utwórz i wypełnij tablicę
temps = array::new(21.5, 22.0, 19.8, 23.1)
std::print(str::fmt("Długość przed wyczyszczeniem: {}", array::len(temps))) // 4

// Wyczyść wszystkie elementy
array::clear(temps)
std::print(str::fmt("Długość po wyczyszczeniu: {}", array::len(temps))) // 0

// Tablica może być ponownie użyta
array::append(temps, 25.0)
array::append(temps, 26.5)
// temps teraz zawiera: [25.0, 26.5]

// Przydatne do okresowego zbierania danych - wyczyść stare odczyty
readings = array::new(0.0)
// ... zbieraj odczyty ...
array::append(readings, 1.5)
array::append(readings, 2.3)
// ... przetwórz odczyty ...
// Zresetuj dla następnego cyklu zbierania
array::clear(readings)

# Operacje na mapach

Ta sekcja opisuje funkcje do tworzenia i manipulowania mapami (słownikami klucz-wartość). Mapy w Volang używają łańcuchów jako kluczy i mogą przechowywać wartości dowolnego typu.

# map::new

Tworzy nową pustą mapę. Mapa to kolekcja par klucz-wartość, gdzie klucze są zawsze łańcuchami. Wartości mogą być dowolnego typu (liczby, łańcuchy, wartości logiczne, tablice lub inne mapy). Mapy są przydatne do przechowywania danych strukturalnych, ustawień konfiguracyjnych lub reprezentowania obiektów podobnych do JSON.

Parametry:

  • Brak.

Zwraca:

  • Nieprzezroczysty uchwyt reprezentujący utworzoną mapę. Ten uchwyt powinien być przekazywany do innych funkcji mapowych (takich jak map::set, map::get, map::contains) w celu manipulowania zawartością mapy.

Przykład:

// Utwórz pustą mapę
config = map::new()

// Mapa jest teraz gotowa do przechowywania par klucz-wartość
// map::set(config, "temperature", 22.5)
// map::set(config, "location", "Salon")

// Mapy są również zwracane przez niektóre funkcje, np. nagłówki odpowiedzi HTTP
// W callbacku http::on_response parametr 'headers' jest mapą

# map::len

Zwraca liczbę par klucz-wartość aktualnie przechowywanych w mapie. Ta funkcja jest przydatna do sprawdzania, czy mapa jest pusta lub określania, ile zawiera wpisów.

Parametry:

  • map: Nieprzezroczysty uchwyt mapy zwrócony przez map::new.

Zwraca:

  • Wartość całkowitą reprezentującą liczbę par klucz-wartość w mapie.

Przykład:

config = map::new()

// Sprawdź rozmiar pustej mapy
count = map::len(config) // Zwraca 0

// Po dodaniu elementów, liczba rośnie
// map::set(config, "temperature", 22.5)
// map::set(config, "humidity", 45)
// count = map::len(config) // Zwraca 2

// Sprawdź, czy mapa jest pusta
if (map::len(config) == 0) {
    std::print("Mapa jest pusta")
}

# map::set

Dodaje lub aktualizuje wartość dla określonego klucza w mapie. Jeśli klucz nie istnieje, tworzona jest nowa para klucz-wartość. Jeśli klucz już istnieje, wartość jest zastępowana nową, ale nowa wartość musi być tego samego typu co istniejąca wartość.

Parametry:

  • map: Nieprzezroczysty uchwyt mapy zwrócony przez map::new.
  • key: Łańcuch określający nazwę klucza.
  • value: Wartość do zapisania. Może być dowolnego typu (liczba, łańcuch, wartość logiczna, tablica lub inna mapa).

Zwraca:

  • Nic.

Przykład:

config = map::new()

// Dodaj nowe pary klucz-wartość
map::set(config, "temperature", 22.5)
map::set(config, "location", "Salon")
map::set(config, "active", true)

// Aktualizuj istniejącą wartość (wymagany ten sam typ)
map::set(config, "temperature", 23.0) // OK - float do float

// Przechowuj różne typy pod różnymi kluczami
map::set(config, "sensor_count", 5)      // integer
map::set(config, "sensor_name", "temp1") // string
map::set(config, "enabled", true)        // boolean

# map::get

Pobiera wartość powiązaną z określonym kluczem z mapy. Typ zwracany zależy od tego, co zostało zapisane pod tym kluczem.

Parametry:

  • map: Nieprzezroczysty uchwyt mapy zwrócony przez map::new.
  • key: Łańcuch określający nazwę klucza do pobrania.

Zwraca:

  • Wartość przechowywaną pod określonym kluczem. Typ zwracany odpowiada typowi przechowywanej wartości.
Warning

Określony klucz musi istnieć w mapie. Próba pobrania wartości dla nieistniejącego klucza spowoduje błąd wykonania. Zawsze używaj map::contains, aby zweryfikować istnienie klucza przed wywołaniem tej funkcji.

Przykład:

config = map::new()
map::set(config, "temperature", 22.5)
map::set(config, "location", "Salon")

// Bezpieczny dostęp: najpierw sprawdź, czy klucz istnieje
if (map::contains(config, "temperature")) {
    temp = map::get(config, "temperature")
    std::print(str::fmt("Temperatura: {}°C", temp))
}

// Dostęp do wartości, gdy wiesz, że klucz istnieje
location = map::get(config, "location") // Zwraca "Salon"

// NIEBEZPIECZNE: Nigdy nie rób tego bez sprawdzenia!
// value = map::get(config, "nonexistent") // Błąd wykonania!

# map::clear

Usuwa wszystkie pary klucz-wartość z mapy, pozostawiając ją pustą. Po wywołaniu tej funkcji map::len(map) zwróci 0. Ta funkcja jest przydatna do ponownego wykorzystania mapy bez tworzenia nowej.

Parametry:

  • map: Nieprzezroczysty uchwyt mapy zwrócony przez map::new.

Zwraca:

  • Nic.

Przykład:

config = map::new()
map::set(config, "temperature", 22.5)
map::set(config, "humidity", 45)
std::print(str::fmt("Rozmiar przed wyczyszczeniem: {}", map::len(config))) // 2

// Wyczyść wszystkie wpisy
map::clear(config)
std::print(str::fmt("Rozmiar po wyczyszczeniu: {}", map::len(config))) // 0

// Mapa może być ponownie użyta
map::set(config, "new_key", "new_value")

# map::contains

Sprawdza, czy określony klucz istnieje w mapie. Ta funkcja powinna być używana przed wywołaniem map::get, aby uniknąć błędów wykonania przy dostępie do nieistniejących kluczy.

Parametry:

  • map: Nieprzezroczysty uchwyt mapy zwrócony przez map::new.
  • key: Łańcuch określający nazwę klucza do sprawdzenia.

Zwraca:

  • true, jeśli klucz istnieje w mapie; w przeciwnym razie zwraca false.

Przykład:

config = map::new()
map::set(config, "temperature", 22.5)
map::set(config, "location", "Salon")

// Sprawdź, czy klucz istnieje
if (map::contains(config, "temperature")) {
    std::print("Klucz temperature istnieje")
    temp = map::get(config, "temperature")
}

// Sprawdź nieistniejący klucz
if (map::contains(config, "humidity")) {
    humidity = map::get(config, "humidity")
} else {
    std::print("Wilgotność nie ustawiona")
}

// Użyj w logice warunkowej
key = "location"
if (map::contains(config, key)) {
    value = map::get(config, key)
    std::print(str::fmt("Znaleziono {}: {}", key, value))
}

# map::keys

Zwraca tablicę zawierającą wszystkie klucze aktualnie przechowywane w mapie. Zwróconą tablicę można iterować za pomocą array::len i array::get_at, aby przetworzyć każdy klucz. Kolejność kluczy nie jest gwarantowana.

Parametry:

  • map: Nieprzezroczysty uchwyt mapy zwrócony przez map::new.

Zwraca:

  • Tablicę łańcuchów, gdzie każdy element jest kluczem z mapy.

Przykład:

settings = map::new()
map::set(settings, "brightness", 80)
map::set(settings, "color", "warm")
map::set(settings, "enabled", true)

keys = map::keys(settings)
i = 0
while (i < array::len(keys)) {
    key = array::get_at(keys, i)
    value = map::get(settings, key)
    std::print(str::fmt("{} = {}", key, value))
    i = i + 1
}

# map::values

Zwraca tablicę zawierającą wszystkie wartości aktualnie przechowywane w mapie. Zwróconą tablicę można iterować za pomocą array::len i array::get_at. Kolejność wartości odpowiada kolejności kluczy zwracanych przez map::keys.

Parametry:

  • map: Nieprzezroczysty uchwyt mapy zwrócony przez map::new.

Zwraca:

  • Tablicę wartości, gdzie każdy element jest wartością z mapy. Elementy mogą być dowolnego typu.

Przykład:

sensors = map::new()
map::set(sensors, "temp", 22.5)
map::set(sensors, "humidity", 65)

values = map::values(sensors)
i = 0
while (i < array::len(values)) {
    std::print(array::get_at(values, i))
    i = i + 1
}

# Operacje JSON

Ta sekcja opisuje funkcje do pracy z danymi JSON. JSON (JavaScript Object Notation) to popularny format wymiany danych, szczególnie przy komunikacji z API webowymi.

# json::get

Wyodrębnia wartość z łańcucha JSON używając ścieżki w notacji kropkowej. Ta funkcja parsuje JSON i nawiguje przez zagnieżdżone obiekty, aby pobrać wartość w określonej lokalizacji.

Parametry:

  • json: Łańcuch zawierający poprawne dane JSON.
  • path: Łańcuch określający ścieżkę do żądanego pola w notacji kropkowej (np. "a.b.c.d").

Zwraca:

  • Wartość pod określoną ścieżką. Typ zwracany zależy od typu wartości JSON: string, number, bool lub array (ten sam typ tablicy co opisany w Operacjach na tablicach, używalny z funkcjami array::*).

Przykład:

// Prosty obiekt JSON
json_data = """{"temperature": 22.5, "location": "Salon", "active": true}"""
temp = json::get(json_data, "temperature") // Zwraca 22.5
location = json::get(json_data, "location") // Zwraca "Salon"
active = json::get(json_data, "active") // Zwraca true

// Zagnieżdżony obiekt JSON
nested = """{"sensor": {"id": "temp1", "value": 23.5, "enabled": false}}"""
sensor_id = json::get(nested, "sensor.id") // Zwraca "temp1"
sensor_value = json::get(nested, "sensor.value") // Zwraca 23.5
sensor_enabled = json::get(nested, "sensor.enabled") // Zwraca false

// Głęboko zagnieżdżona struktura
deep = """{"building": {"floor": {"room": {"temperature": 22.0}}}}"""
room_temp = json::get(deep, "building.floor.room.temperature") // Zwraca 22.0

// Pobieranie tablicy
json_with_array = """{"readings": [21.5, 22.0, 22.5]}"""
readings = json::get(json_with_array, "readings") // Zwraca tablicę [21.5, 22.0, 22.5]

# Operacje HTTP

Ta sekcja opisuje funkcje do wykonywania żądań HTTP do zewnętrznych serwisów. Funkcje te umożliwiają skryptom Volang komunikację z API webowymi, wysyłanie powiadomień lub integrację z usługami zewnętrznymi.

# http::client

Tworzy nową instancję klienta HTTP wymaganą do wykonywania żądań HTTP. Klient zarządza ustawieniami połączenia, obsługuje wykonywanie żądań i musi zostać utworzony przed wywołaniem jakiejkolwiek innej funkcji HTTP.

Parametry:

  • Brak.

Zwraca:

  • Nieprzezroczysty uchwyt reprezentujący klienta HTTP. Ten uchwyt powinien być przekazywany do innych funkcji HTTP (takich jak http::call) w celu wykonywania żądań.

Przykład:

// Utwórz klienta HTTP
client = http::client()

// Klient jest teraz gotowy do wykonywania żądań

# http::set_method

Ustawia metodę HTTP dla żądania. Ta funkcja musi zostać wywołana przed wykonaniem żądania za pomocą http::call. Jeśli nie zostanie ustawiona, domyślną metodą jest GET.

Parametry:

  • client: Nieprzezroczysty uchwyt klienta HTTP zwrócony przez http::client.
  • method: Łańcuch określający metodę HTTP. Obsługiwane wartości: "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS".

Zwraca:

  • Nic.

Przykład:

client = http::client()

// Ustaw metodę na POST do wysyłania danych
http::set_method(client, "POST")

// Ustaw metodę na GET do pobierania danych (to jest domyślne)
http::set_method(client, "GET")

// Ustaw metodę na PUT do aktualizacji zasobów
http::set_method(client, "PUT")

// Ustaw metodę na DELETE do usuwania zasobów
http::set_method(client, "DELETE")

# http::set_header

Dodaje niestandardowy nagłówek HTTP do żądania. Ta funkcja może być wywoływana wielokrotnie, aby dodać wiele nagłówków. Nagłówki służą do przekazywania dodatkowych informacji wraz z żądaniem, takich jak tokeny uwierzytelniające, specyfikacje typu zawartości lub niestandardowe metadane.

Parametry:

  • client: Nieprzezroczysty uchwyt klienta HTTP zwrócony przez http::client.
  • key: Łańcuch określający nazwę nagłówka (np. "Content-Type", "Authorization").
  • value: Łańcuch określający wartość nagłówka.

Zwraca:

  • Nic.

Przykład:

client = http::client()
http::set_method(client, "POST")

// Ustaw typ zawartości dla danych JSON
http::set_header(client, "Content-Type", "application/json")

// Dodaj nagłówek autoryzacji z kluczem API
http::set_header(client, "Authorization", "Bearer my-api-token-123")

// Dodaj niestandardowe nagłówki
http::set_header(client, "X-Custom-Header", "custom-value")
http::set_header(client, "Accept", "application/json")

# http::set_body

Ustawia zawartość ciała żądania. Ta funkcja jest zazwyczaj używana z żądaniami POST, PUT lub PATCH do wysyłania danych na serwer. Ciało może zawierać JSON, dane formularza lub dowolną inną treść tekstową. Pamiętaj, aby ustawić odpowiedni nagłówek Content-Type za pomocą http::set_header, aby dopasować go do formatu ciała.

Parametry:

  • client: Nieprzezroczysty uchwyt klienta HTTP zwrócony przez http::client.
  • body: Łańcuch zawierający zawartość ciała żądania.

Zwraca:

  • Nic.

Przykład:

client = http::client()
http::set_method(client, "POST")
http::set_header(client, "Content-Type", "application/json")

// Ustaw ciało JSON
http::set_body(client, """{"temperature": 22.5, "humidity": 45}""")

// Lub zbuduj ciało dynamicznie używając str::fmt
temp = 22.5
humidity = 45
body = str::fmt("""{"temperature": {}, "humidity": {}}""", temp, humidity)
http::set_body(client, body)

# http::call

Wykonuje żądanie HTTP na podany URL używając skonfigurowanych ustawień klienta (metoda, nagłówki, ciało). Ta funkcja jest asynchroniczna - wysyła żądanie i natychmiast zwraca sterowanie. Odpowiedź jest dostarczana poprzez funkcję callback http::on_response, która musi być zdefiniowana w skrypcie. Obsługiwane protokoły to http:// i https://.

Parametry:

  • client: Nieprzezroczysty uchwyt klienta HTTP zwrócony przez http::client.
  • url: Łańcuch zawierający pełny URL, na który ma zostać wysłane żądanie.

Zwraca:

  • Nic. Odpowiedź jest dostarczana asynchronicznie poprzez callback http::on_response.

Callback: http::on_response(status, body, headers)

Aby otrzymać odpowiedź HTTP, musisz zdefiniować zewnętrzną funkcję callback o następującej sygnaturze:

extern fn http::on_response(status, body, headers) {
    // Tutaj obsłuż odpowiedź
}

Parametry callbacka:

  • status: Liczba całkowita reprezentująca kod statusu HTTP (np. 200 dla sukcesu, 404 dla nie znaleziono, 500 dla błędu serwera).
  • body: Łańcuch zawierający treść ciała odpowiedzi.
  • headers: Obiekt mapy (zobacz Operacje na mapach) zawierający nagłówki odpowiedzi jako pary klucz-wartość.

Przykład:

// Zdefiniuj callback odpowiedzi - zostanie wywołany gdy nadejdzie odpowiedź
extern fn http::on_response(status, body, headers) {
    if (status == 200) {
        std::print(str::fmt("Sukces! Odpowiedź: {}", body))
    } else {
        std::print(str::fmt("Błąd: HTTP {}", status))
    }
}

// Przygotuj i wyślij żądanie
client = http::client()
http::set_method(client, "GET")
http::set_header(client, "Accept", "application/json")
http::call(client, "http://192.168.1.100/api/status")

// Dla żądania POST z danymi
client2 = http::client()
http::set_method(client2, "POST")
http::set_header(client2, "Content-Type", "application/json")
http::set_body(client2, """{"command": "turn_on"}""")
http::call(client2, "http://192.168.1.100/api/device/relay1")

# Operacje czasowe

# time::now

Pobiera bieżący czas systemowy jako znacznik czasu Unix. Wartość reprezentuje liczbę sekund, które upłynęły od 00:00:00 UTC 1 stycznia 1970 roku (Epoka Unix).

Ta funkcja jest niezbędna do śledzenia, kiedy wystąpiły zdarzenia, obliczania czasu, który upłynął między akcjami, lub synchronizacji z serwerami zewnętrznymi.

Parametry:

  • Brak.

Zwraca:

  • Wartość całkowitą reprezentującą bieżący znacznik czasu Unix (w sekundach).

Przykład:

// Zapisz czas, kiedy ostatnio wykryto ruch
last_motion_time = time::now()

// ... później w kodzie ...

// Sprawdź, czy od ostatniego ruchu minęło więcej niż 60 sekund
if (time::now() > last_motion_time + 60) {
   ...
}

# time::uptime

Zwraca liczbę sekund, które upłynęły od włączenia modułu lub jego ostatniego restartu. Ta wartość jest przydatna do monitorowania stanu systemu, wykrywania nieoczekiwanych restartów lub implementacji logiki czasowej, która powinna się resetować po cyklu zasilania.

W przeciwieństwie do time::now(), która zwraca bezwzględny znacznik czasu, time::uptime() zwraca pomiar względny, który zaczyna się od zera przy każdym uruchomieniu modułu.

Parametry:

  • Brak.

Zwraca:

  • Wartość całkowitą reprezentującą liczbę sekund od uruchomienia modułu.

Przykład:

// Zapisz ostrzeżenie, jeśli moduł działa dłużej niż 24 godziny
// (może wskazywać, że nie był restartowany w celu konserwacji)
if (time::uptime() > 86400) {
    std::print("Moduł działa ponad 24 godziny")
}

// Opóźnij logikę inicjalizacji, aż moduł będzie stabilny przez 10 sekund
if (time::uptime() > 10) {
    // Można założyć, że wszystkie czujniki zostały zainicjalizowane
    ...
}

// Wykryj, czy moduł został niedawno zrestartowany
if (time::uptime() < 60) {
    std::print("Moduł właśnie wystartował, inicjalizacja...")
}

# Operacje matematyczne

# math::abs

Oblicza wartość bezwzględną liczby. Jeśli dane wejściowe są ujemne, zwraca dodatni odpowiednik; jeśli dane wejściowe są dodatnie, zwraca wartość bez zmian. Ta funkcja obsługuje zarówno typy całkowite, jak i zmiennoprzecinkowe.

Jest szczególnie przydatna do obliczania różnicy (delty) między dwoma odczytami czujników bez martwienia się o to, która wartość jest większa (np. sprawdzanie, czy temperatura zmieniła się o więcej niż 1 stopień w dowolnym kierunku).

Parametry:

  • value: Liczba do przetworzenia.

Zwraca:

  • Wartość numeryczną reprezentującą nieujemną wartość danych wejściowych. Typ zwracany odpowiada typowi wejściowemu.

Przykład:

target_temp = 21.0
current_temp = 19.5

// Oblicz różnicę ignorując kierunek
delta = math::abs(target_temp - current_temp)

// Jeśli różnica jest znacząca (więcej niż 0,5 stopnia), podejmij działanie
if (delta > 0.5) {
    ....
}

# math::round

Zaokrągla podaną liczbę zmiennoprzecinkową do najbliższej wartości całkowitej. Przypadki graniczne (gdzie część ułamkowa wynosi dokładnie 0.5) są zaokrąglane od zera.

Parametry:

  • value: Liczba do zaokrąglenia.

Zwraca:

  • Liczbę całkowitą reprezentującą najbliższą liczbę całkowitą.

Przykład:

// Przykład 1: Zaokrąglanie danych z czujnika do wyświetlenia
rawTemp = 21.7
displayTemp = math::round(rawTemp) // Zwraca 22

// Przykład 2: Przypadki graniczne (zaokrąglanie od zera)
val1 = math::round(2.5)  // Zwraca 3
val2 = math::round(-2.5) // Zwraca -3

// Ustawienie poziomu ściemniacza (musi być liczbą całkowitą 0-100)
calculatedLevel = 55.4
dimmerLevel = math::round(calculatedLevel) // Zwraca 55

# math::random

Zwraca pseudolosową liczbę zmiennoprzecinkową z zakresu [0.0, 1.0). Każde wywołanie zwraca inną wartość. Wynik można skalować i łączyć z math::round, aby uzyskać losowe liczby całkowite w wybranym zakresie.

Parametry:

Brak.

Zwraca:

  • Wartość zmiennoprzecinkową większą lub równą 0.0 i mniejszą niż 1.0.

Przykład:

// Pobierz losową wartość z zakresu 0.0 do 1.0
r = math::random()

// Wygeneruj losową liczbę całkowitą od 1 do 100
n = math::round(math::random() * 100) + 1

// Losowa decyzja (50/50)
if (math::random() < 0.5) {
    output::set("led", true)
} else {
    output::set("led", false)
}

# Operacje Base64

Ta sekcja opisuje funkcje do kodowania danych za pomocą schematów kodowania Base64.

# base64::encode

Koduje łańcuch do jego reprezentacji Base64 używając standardowego alfabetu (RFC 4648 Tabela 1). Wynik używa znaków A-Z, a-z, 0-9, +, / i jest dopełniany znakami =, aby zapewnić, że długość wyniku jest wielokrotnością 4.

Parametry:

  • data (string): Łańcuch wejściowy do zakodowania.

Zwraca:

  • Łańcuch zawierający reprezentację danych wejściowych zakodowaną w Base64.

Przykład:

// Zakoduj prosty łańcuch
encoded = base64::encode("Hello, World!") // Zwraca "SGVsbG8sIFdvcmxkIQ=="

// Zakoduj dane uwierzytelniające dla HTTP Basic Auth
credentials = str::concat("user", ":", "password")
auth = str::concat("Basic ", base64::encode(credentials))
http::set_header(client, "Authorization", auth)

// Pusty łańcuch koduje się do pustego łańcucha
encoded = base64::encode("") // Zwraca ""

# base64::url_encode

Koduje łańcuch do jego reprezentacji Base64url używając alfabetu bezpiecznego dla URL (RFC 4648 Tabela 2). Wynik używa znaków A-Z, a-z, 0-9, -, _ i nie zawiera znaków dopełnienia. To kodowanie jest bezpieczne do użycia w adresach URL, parametrach zapytań i segmentach JWT.

Parametry:

  • data (string): Łańcuch wejściowy do zakodowania.

Zwraca:

  • Łańcuch zawierający reprezentację danych wejściowych zakodowaną w Base64url, bez dopełnienia.

Przykład:

// Zakoduj do formatu bezpiecznego dla URL
encoded = base64::url_encode("Hello, World!") // Zwraca "SGVsbG8sIFdvcmxkIQ"

// Zbuduj nagłówek i ładunek JWT
header = base64::url_encode("""{"alg":"RS256","typ":"JWT"}""")
payload = base64::url_encode("""{"sub":"1234567890","name":"John"}""")
signing_input = str::concat(header, ".", payload)

// Zwróć uwagę na różnicę w porównaniu ze standardowym base64:
// base64::encode("subjects?_d")     zwraca "c3ViamVjdHM/X2Q="
// base64::url_encode("subjects?_d") zwraca "c3ViamVjdHM_X2Q"

# Operacje kryptograficzne

Ta sekcja opisuje funkcje do wykonywania operacji kryptograficznych.

# crypto::rs256_sign

Podpisuje dane za pomocą klucza prywatnego RSA algorytmem RS256 (RSASSA-PKCS1-v1_5 z użyciem SHA-256). Ta funkcja jest zazwyczaj używana do tworzenia podpisów JWT lub innych uwierzytelnionych wiadomości.

Parametry:

  • data (string): Dane do podpisania.
  • private_key_pem (string): Klucz prywatny RSA w formacie PEM.

Zwraca:

  • Łańcuch zawierający podpis zakodowany w Base64url.

Przykład:

// Utwórz podpis JWT
header = base64::url_encode("""{"alg":"RS256","typ":"JWT"}""")
payload = base64::url_encode("""{"sub":"device-001","iat":1700000000}""")
signing_input = str::concat(header, ".", payload)

// Podpisz kluczem prywatnym
signature = crypto::rs256_sign(signing_input, private_key)

// Złóż kompletny JWT
jwt = str::concat(signing_input, ".", signature)

# Operacje asynchroniczne

Ta sekcja opisuje funkcje callback, które można zdefiniować do obsługi asynchronicznych zdarzeń i odpowiedzi.

Dokumentacja referencyjna funkcji i modułów biblioteki standardowej Volang.