Esempi di script
Script TapHome completi: divisione sicura, 0 invece di un valore sconosciuto, dimmerazione con LINEAR, allarmi e attributi di servizio Modbus, HTTP e JSON, listener MQTT e Wake on LAN.
Script completi per attività comuni. Le ricette per smart rule funzionano in qualsiasi installazione; gli esempi Modbus e Packet parser provengono dai repository ufficiali dei modelli per Modbus e Packet parser. I nomi brevi come Se, va1 o St sono abbreviazioni dei valori dei dispositivi scelti nell’editor degli script; nomi come StatusJson o plugTopic sono variabili del modulo.
Ricette per smart rule
Dividere due valori in modo sicuro
Dividere per un valore di dispositivo pari a 0 interrompe lo script con Line in script: 1 Message: Division by zero. Racchiudi la divisione va1/va2 nella forma a funzione di IF. Valuta solo il ramo scelto, quindi la divisione viene eseguita solo quando il divisore è maggiore di 0:
IF(va2 > 0, va1/va2, 0);
# Result: 0 when va2 is 0, otherwise va1 divided by va2Quando il divisore può essere negativo, verifica invece va2 <> 0. Maggiori dettagli in Errori.
Scrivere 0 invece di un valore sconosciuto
Un valore di dispositivo sconosciuto, ad esempio da un sensore in errore, è NaN. Per scrivere invece 0, verificalo con ISNAN — lo schema è IF(ISNAN(x), 0, x):
IF(ISNAN(Se), 0, Se);
# Result: 0 while the value of Se is unknown, otherwise the value of SeUn confronto come Se = NaN è un errore di parsing. Quando il valore può essere anche Null (nessun valore), verifica prima ISNULL; OR salta il lato destro quando il lato sinistro è TRUE:
IF(ISNULL(Se) OR ISNAN(Se), 0, Se);Dimmerazione con LINEAR
LINEAR converte un intervallo di valori di ingresso in un intervallo di valori di uscita, ed è il modo abituale per calcolare un livello di dimmerazione. Il livello di un dimmer va da 0 (spento) a 1 (100 %). In una smart rule Formula con un dimmer come uscita, questo script abbassa la luce man mano che la luce diurna sale da 0 a 500 lx (Se è il sensore di luminosità):
LINEAR(Se, 0, 1, 500, 0);
# Result: 1 at 0 lx, 0.5 at 250 lx, 0 at 500 lx and moreFuori dall’intervallo di ingresso il risultato resta all’estremo più vicino (BOUNDS, il valore predefinito). Per mantenere un livello minimo, alza l’uscita inferiore: LINEAR(Se, 0, 1, 500, 0.1) non scende mai sotto il 10 %. Dettagli in LINEAR.
Esempi Modbus
Errori del dispositivo da un registro di allarme
Uno script di lettura di un inverter Solax trasforma un registro di stato e una parola di allarme a 32 bit in errori del dispositivo:
VAR reg := MODBUSR(A, 0x09, UInt16);
IF(reg = 3, ADDERROR("Run Mode Fault"));
IF(reg = 4, ADDERROR("Run Mode Permanent Fault"));
VAR x3 := MODBUSR(A, 0x0040, Uint32);
IF(GETBIT(x3, 0) = 1, ADDERROR("TZ Protect Fault"));
IF(GETBIT(x3, 1) = 1, ADDERROR("Grid Lost Fault"));
IF(GETBIT(x3, 2) = 1, ADDERROR("Grid Volt Fault"));
IF(GETBIT(x3, 15) = 1, ADDERROR("Off-grid Overload"));Attributo di servizio da campi di bit
Un attributo di servizio Komfovent mostra i quattro byte di un registro a 32 bit come testo separato da punti:
VAR reg := MODBUSR(H, 22, Uint32);
VAR first := GETBITS(reg, 0, 8);
VAR second := GETBITS(reg, 8, 8);
VAR third := GETBITS(reg, 16, 8);
VAR last := GETBITS(reg, 24, 8);
RETURN(last + "." + third + "." + second + "." + first);
# Result: text such as "1.2.3.4"Azione di servizio con un parametro
I parametri di un’azione di servizio sono variabili denominate con la loro abbreviazione. Un’azione di Eastron SDM120 scrive il suo parametro ID nell’holding register 20:
MODBUSW(H, 20, Float, ID)Decodificare un’enumerazione
Un registro di stato di Huawei SUN2000 diventa un testo leggibile con SWITCH:
VAR state := MODBUSR(H, 32089, Uint16);
SWITCH(state,
0, "Idle: Initializing",
1, "Idle: Detecting ISO",
256, "Starting",
512, "On-Grid",
768, "Shutdown: Fault",
"Unknown");Esempi Packet parser
Richiesta HTTP con gestione degli errori
SENDHTTPREQUEST restituisce un oggetto httpresponse. Questo script di lettura (Forecast.solar) conserva il corpo della risposta nella variabile output per il parsing successivo e segnala una richiesta non riuscita come errore del dispositivo:
VAR response := SENDHTTPREQUEST("/estimate/" + Latitude + "/" + Longitude + "/"
+ PV_declination + "/" + PV_azimuth + "/" + PV_kWp,
"GET", "", "Accept: application/json");
IF response.IsSuccess
output := response.Content;
ELSE
ADDERROR(response.StatusCode + " (" + response.ReasonPhrase + ")");
ENDTempo di attività da JSON
Un attributo di servizio di Shelly 1PM formatta il tempo di attività in secondi a partire dal JSON di stato in cache:
VAR upTimeSeconds := PARSEJSON(StatusJson, "uptime");
VAR days := FLOOR(upTimeSeconds / 86400, 1);
upTimeSeconds := MOD(upTimeSeconds, 86400);
VAR hours := FLOOR(upTimeSeconds / 3600, 1);
upTimeSeconds := MOD(upTimeSeconds, 3600);
VAR minutes := FLOOR(upTimeSeconds / 60, 1);
days + " day(s) " + hours + "h " + minutes + "m";
# Result: for 191820 seconds "2 day(s) 5h 17m"Prezzo spot per il periodo corrente
Uno script di lettura scarica i prezzi di oggi da okte.sk:
VAR today := TOSTRING(NOW(), "yyyy-MM-dd");
VAR response := SENDHTTPREQUEST("/api/v1/dam/results?deliveryDayFrom=" + today
+ "&deliveryDayTo=" + today);
IF response.IsSuccess
output := response.Content;
ELSE
ADDERROR(response.StatusCode + " (" + response.ReasonPhrase + ")");
ENDUn attributo di servizio sceglie poi un periodo con un filtro JSONPath:
PARSEJSON(output, "$[?(@.period == 1)].price") + " EUR"Ciclo su un array JSON
Con TRUE come terzo argomento, PARSEJSON restituisce Null dopo l’ultimo elemento invece di fallire, il che termina il ciclo:
VAR response := SENDHTTPREQUEST("/api/taphomeapi/v1/discovery", "GET", "",
"Authorization: TapHome " + API_token);
IF response.IsSuccess
VAR ret := "";
VAR i := 0;
VAR id := PARSEJSON(response.Content, "$.devices[0].deviceId", TRUE);
WHILE !ISNULL(id)
ret := ret + "(" + id + ") ";
ret := ret + PARSEJSON(response.Content, "$.devices[" + TOSTRING(i) + "].name", TRUE);
ret := ret + " - " + PARSEJSON(response.Content, "$.devices[" + TOSTRING(i) + "].type", TRUE);
ret := ret + "\n";
i := i + 1;
id := PARSEJSON(response.Content, "$.devices[" + TOSTRING(i) + "].deviceId", TRUE);
LOOP
RETURN(ret);
ENDValidare una variabile del modulo in uno script listener
Uno script listener MQTT di Shelly verifica prima che la variabile del modulo plugTopic sia stata compilata, poi converte la potenza misurata da W a kW:
IF(INDEXOF(plugTopic, "shelly1pm-deviceid") = 0)
ADDERROR("Set correct 'plugTopic' value in module variables. "
+ "Topic format is 'shelly1pm-<deviceid>'.");
RETURN(-1);
END
IF(RECEIVEDMSG.TOPIC = "shellies/" + plugTopic + "/relay/0/power")
VAR valueP := TOSTRING(RECEIVEDMSG.PAYLOAD);
Ed := IF(ISNULL(valueP), NaN, TODOUBLE(valueP) / 1000.0);
ENDWake on LAN
Un pulsante UDP invia un magic packet. La variabile del modulo MAC contiene l’indirizzo come testo ("12 34 56 78 9a bc"); BYTECOLLECTION ignora gli spazi:
VAR magicPacket := BYTECOLLECTION("FF FF FF FF FF FF " + MAC + MAC + MAC + MAC
+ MAC + MAC + MAC + MAC + MAC + MAC + MAC + MAC + MAC + MAC + MAC + MAC);
SENDDATA(magicPacket);