Przykład: monitoring temperatury
Zakres weryfikacji
Treść zachowana z obecnego źródła. Publikacja dokumentacji nie oznacza ponownego potwierdzenia wszystkich komend, przykładów i deklaracji możliwości.
Poziom: średniozaawansowany — trzy środowiska, jawne artefakty i kontrola przed lokalnym uruchomieniem.
Ten przykład pokazuje cały model Junexis w jednym projekcie: czujnik na
urządzeniu, przetwarzanie na serwerze i prezentację alertów w interfejsie.
Odpowiada projektowi examples/projects/01-temperature-monitor w repozytorium
języka.
System
flowchart LR
SENSOR["TempSensor<br/>@embedded"] -->|"chan<TempReading>"| PROCESS["TempProcessor<br/>@server"]
PROCESS -->|"chan<Alert>"| DASH["AlertDashboard<br/>@report"]
SENSOR -.->|"zdarzenia"| OBS["Obserwacja"]
PROCESS -.->|"zdarzenia"| OBS
DASH -.->|"zdarzenia"| OBS
OBS --> STORY["Narrative<br/>historia wykonania"]
Manifest projektu
name = "temperature-monitor"
entry = "src/main.jnx"
targets = ["embedded", "server", "report"]
outDir = "out"
Manifest wskazuje jeden plik wejściowy i trzy środowiska docelowe. Kod
generowany trafia do out/, natomiast pliki należące do autora projektu można
utrzymywać w katalogu user/.
Wspólne dane
struct TempReading {
celsius: Float
device_id: Text
timestamp: Time
}
struct Alert {
level: Text
message: Text
value: Float
at: Time
}
Te same typy są sprawdzane po obu stronach granic między urządzeniem, serwerem i interfejsem.
Zadanie urządzenia
extern task dht_read_celsius(pin: u8) @embedded -> Float
task TempSensor() @embedded(kitchen_sensor) -> chan<TempReading> {
config {
dht22_pin: u8 : 4
device_id: Text : "kitchen"
}
every 5s {
let temp = dht_read_celsius(config.dht22_pin)
send TempReading {
celsius: temp,
device_id: config.device_id,
timestamp: now()
}
}
}
extern task wyznacza granicę kodu należącego do autora. Junexis opisuje
kontrakt odczytu, ale implementacja sterownika czujnika pozostaje w kodzie
urządzenia.
Zadanie serwerowe
task TempProcessor(
readings: chan<TempReading>
) @server -> chan<Alert> {
config {
high_threshold: Float : 30.0
low_threshold: Float : 10.0
}
loop {
let reading = recv readings
if reading.celsius > config.high_threshold {
send Alert {
level: "HIGH",
message: "Temperature too high",
value: reading.celsius,
at: reading.timestamp
}
}
}
}
Serwer odbiera typowane dane i publikuje alert. Kompilator sprawdza typy, liczbę argumentów i zgodność połączeń przed wygenerowaniem Go.
Zadanie interfejsu
extern task render_alert(alert: Alert) @report
task AlertDashboard(alerts: chan<Alert>) @report {
for alert in alerts {
log("ALERT {alert.message}")
render_alert(alert)
}
}
Warstwa @report otrzymuje TypeScript oraz kontrakt funkcji, którą autor
łączy z własnym interfejsem.
Potok wykonania
pipeline TempMonitoring {
use TempSensor -> TempProcessor
use TempProcessor -> AlertDashboard
}
Potok pozwala kompilatorowi zbudować topologię, dobrać generatory i wykryć niezgodne lub brakujące połączenia.
Sprawdzenie i budowanie
Z katalogu zawierającego repozytoria platformy:
$project = ".\junexis-lang\examples\projects\01-temperature-monitor"
junexis check $project
junexis build $project
Wynik
out/
├── embedded/ # C++ i projekt PlatformIO
├── server/ # moduł Go
├── report/ # projekt TypeScript
├── analysis/ # model systemu dla narzędzi
├── debug/ # mapy źródeł i manifest debugowania
└── junexis.artifacts.json
flowchart TB
BUILD["Sprawdzony projekt"] --> E["out/embedded"]
BUILD --> S["out/server"]
BUILD --> R["out/report"]
BUILD --> A["out/analysis"]
BUILD --> D["out/debug"]
E --> PACKAGE["Pakiet systemu"]
S --> PACKAGE
R --> PACKAGE
A --> PACKAGE
D --> PACKAGE
Pakowanie i lokalne uruchomienie
$bundle = Join-Path $project "temperature-monitor.system-bundle.zip"
$preflight = Join-Path $project "deployment-preflight.json"
junexis package $project --out $bundle
junexis deploy preflight $bundle --report-out $preflight --target server --target report
junexis deploy local $bundle --preflight $preflight --target server --target report --duration 5
package zapisuje zweryfikowaną paczkę pod jawną ścieżką, deploy preflight
tworzy raport gotowości, a deploy local uruchamia ograniczoną czasowo sesję
części serwerowej i raportowej. Programowanie urządzenia pozostaje jawną,
osobną operacją wymagającą wyboru fizycznego portu.
Co zostało udowodnione
- jeden opis tworzy artefakty C++, Go i TypeScript,
- typy i topologia są sprawdzane przed generowaniem,
- kod autora pozostaje poza katalogiem generowanym,
- artefakty można związać w jedną paczkę systemu,
- identyfikatory budowania łączą paczkę, uruchomienie, obserwację i Narrative.
Ten przykład jest reprezentatywną ścieżką rozwojową. Nie dowodzi jeszcze, że każda konstrukcja języka działa jednakowo na każdym urządzeniu i środowisku.