Sei sulla pagina 1di 10

Il linguaggio di programmazione è derivato da Java, raccolta di enormi in autonomia tapparelle e verande in caso di pioggia

quindi si possono seguire le linee guida di questo quantità di imminente se siamo fuori casa. Potrebbero essere
linguaggio, sempre tenendo conto della gestione ad informazioni da anche più utili delle previsioni nazionali o regionali
eventi dei diversi task concorrenti. Il punto comune sensori sparsi in tutto il che debbono essere, per forza di cose, più generiche.
tra tutte le componenti di OpenHAB sono, come sarà mondo (e fuori da Un algoritmo molto diffuso da anni, utilizzato anche
ormai chiaro, gli item. Possiamo considerarli come le esso) e su stazioni meteo piccole e medie, e che ha bisogno
variabili globali del nostro ambiente di sviluppo. Il all’elaborazione con i solo di poche informazioni, è la versione digitale del
punto sul quale confluiscono tutte le operazioni che computer più potenti metodo Zambretti sperimentato da più di cento anni
abbiamo eseguito in precedenza configurando tramite algoritmi nella sua versione originaria. Vediamo come
binding, thing, channel e che riportano in un predittivi sempre più implementarlo in OpenHAB con i dati che già ci
linguaggio unico dati eterogenei di sensori ed elaborati. In Rete ci fornisce la nostra CM3-Home. In uno dei primi
attuatori basati su tecnologie anche diversissime tra sono diversi servizi articoli abbiamo visto come rappresentare
loro. Gli item sono anche il punto di collegamento tra che espongono delle informazioni meteorologiche su un HABpanel
la parte server (le rule eseguite su OpenHAB nella API per utilizzare i utilizzando un widget personalizzato scritto in HTML
CM3Home) e i client (le GUI che girano sull’app risultati di questi con gli stili definiti in un CSS esterno. I dati raccolti
mobile oppure gli HABpanel basati su widget calcoli anche nei nostri da sensori collegati alla CM3-Home o prelevati da
standard o personalizzati). In quest’ultimo articolo dispositivi; però quelle siti di previsioni meteo on-line sono semplicemente
della serie descriveremo applicazioni che esplicano al così ottenute riportati nella pagina HTML o associati a icone in
meglio le potenzialità di OpenHAB: integrare tra loro rimangono sempre modo automatico. Ora vogliamo realizzare un
le tecnologie più disparate per ottenere un cruscotto previsioni statistiche a pannello più elaborato (Fig. 1) nel quale alcuni dati
di controllo molto potente ma facile da usare. Oltre medio e breve termine sono semplicemente prelevati dai sensori, mentre altri
ad utilizzare diverse componenti hardware, su un territorio esteso. sono elaborati secondo algoritmi molto usati in
disegneremo delle GUI basate sullo stato dell’arte del Dal momento che meteorologia, come il metodo Zambretti e la tabella
software di presentazione, come HTML, CSS, abbiamo a Beaufort. Analizziamo le diverse tecnologie integrate
javascript, AngularJS, Ajax, eccetera. disposizione dei in questo widget: temperatura, umidità, pressione
sensori locali che barometrica e concentrazione di CO2 sono rilevati
analizzano l’ambiente tramite i sensori Netatmo, Sonoff e 1-wire che
SVILUPPO AVANZATO DI RULE che ci circonda, abbiamo già descritto in precedenza. La variazione di
Negli articoli precedenti abbiamo visto come leggere possiamo elaborare pressione è calcolata dai dati storici memorizzati in
informazioni da sensori collegati direttamente o via anche noi delle InfluxDB, anche questo già spiegato. Le previsioni
rete alla CM3-Home, oppure da servizi esterni in previsioni molto loca- per i giorni successivi sono ottenute da servizi
Cloud, ed anche come presentarli in un HABpanel in lizzate e a brevissimo
maniera aggregata e trasparente all’utente. Ora temine che, anche se
spiegheremo come, utilizzando gli stessi dati ma con algoritmi meno
elaborandoli tramite rule avanzate, possiamo ottenere sofisticati, potrebbero
informazioni sull’ambiente. esserci più utili per
sapere se dobbiamo
prendere l’ombrello, se
Ð Fig. 1 è inutile innaffiare il
Esempio di HABpanel meteo avanzato.

giardino o se possiamo
organizzarci per il pic-
METEO
Le previsioni meteorologiche hanno raggiunto dei
nic fuori porta o,
livelli di precisione veramente alti, grazie alla
magari, per comandare
Ð Listato 1
rule “wind”
when Item Wind_Speed received update or Item Wind_Direction received update or Item Wind_Direction_deg received update

then val beaufortText = newArrayList ( ‘Calma’, ‘Bava di vento’, ‘Brezza


leggera’, ‘Brezza tesa’, ‘Vento moderato’, ‘Vento teso’, ‘Vento fresco’,
‘Vento forte’, ‘Burrasca’, ‘Burrasca forte’, ‘Tempesta’, ‘Tempesta violenta’,
‘Uragano’ ) Wind.postUpdate(Wind_Speed.state.toString + “ km/h “ +
Wind_Direction.state.toString) var int beaufortValue =
Math.round(Math.pow((Wind_Speed.state as DecimalType).floatValue /
4,0.707106781)).intValue Wind_Beaufort.postUpdate(beaufortText.get(beaufortValue).toString)
end

meteo on-line. La direzione e la velocità del vento dare risultati affidabili.


possono essere misurate tramite, ad esempio, un
anemometro collegato alla centralina Netatmo. La Esempio di rappresentazione dei parametr
relativa rule è descritta nel Listato 1, dove i dati di
velocità e direzione sono raggruppati in una stringa per
poterli rappresentare su un’unica riga della GUI classica
(Fig. 2). Viene poi calcolato l’indice Beaufort. Usando
questo indice nella tabella beaufortText si può ottenere
la descrizione in chiaro, secondo Beaufort, dell’intensità
del vento. In Fig. 1 si può vedere una situazione di
calma di vento con una direzione di provenienza da
nord-est. Per calcolare le previsioni con il metodo
Zambretti occorre analizzare l’andamento della
pressione, in mbar/h, nelle ultime tre ore, riferito alla
pressio
ne atmosferica a livello del mare. La centralina Netatmo
fornisce il valore di pressione sia assoluta (misurata dal
barometro) sia relativa; questa viene calcolata dalla
centralina conoscendo l’altezza sul livello del mare della
postazione, altezza rilevata a sua volta in fase di
installazione tramite il GPS del telefono sul quale gira
l’app di configurazione. Se si dispone solo della
pressione assoluta è facile calcolare quella relativa
conoscendo l’altezza s.l.m. ed applicando delle semplici
formule reperibili in Rete. Secondo il NOAA (National
Oceanic and Atmospheric Administration) la tendenza
della pressione atmosferica è uguale alla differenza tra
la pressione atmosferica attuale e quella di tre ore prima,
divisa per 3 per ottenere l’andamento orario. La rule è
avviata a tempo ogni 10 minuti, lo stesso periodo con il
quale sono aggiornati i dati della centralina meteo. I dati
storici sono ripresi da InfluxDB, mediando due misure
distanti 12 minuti tra loro per essere sicuri di catturare
due diversi eventi. La pressione massima e quella
minima sono calcolate ad ogni misura e conservate nel
DB per avere una storia del luogo e tarare meglio nel
tempo l’algoritmo Zambretti (Listato 2). L’andamento
della pressione calcolato si usa per assegnare il nome
dell’icona che indicherà l’andamento nel widget e il flag
che sarà usato successivamente per applicare il corretto
algoritmo. Il valore dell’andamento di pressione minimo
che deve essere usato per considerare la pressione
stabile o meno non è molto chiaro, ci sono diverse
interpretazioni. In questo esempio è stato usato il valore
applicato nel codice reperibile all’indirizzo
https://github.com/jim-easterbrook/pywws e sembra
d ”
a )
t
e P
( r
c e
Ð Listato 2 u s
r s
rule “Pressure Trend” when Time cron “0 0/10 * * * ?” then var r u
Number pressure0avg = e r
((Netatmo_Indoor_Pressure.historicState(now.minusMinutes(0)).sta n e
te as t T
DecimalType)+ P r
(Netatmo_Indoor_Pressure.historicState(now.minusMinutes(- r e
12)).state as DecimalType))/2 var Number currentPress = e n
Netatmo_Indoor_Pressure.historicState(now.minusMinutes(0)).s s d
tate as DecimalType var Number maxPress = s F
MaxPressure.historicState(now.minusMinutes(0)).state as ) l
DecimalType var Number minPress = a
MinPressure.historicState(now.minusMinutes(0)).state as } g
DecimalType .
if (currentPress < minPress) p
{ //store the min MinPressure.postUpdate(currentPress) o
i } s
f t
var Number pressure180avg = U
( p
((Netatmo_Indoor_Pressure.historicState(now.minusMinutes(
c d
174)).state as DecimalType)+
u a
(Netatmo_Indoor_Pressure.historicState(now.minusMinutes(1
r t
86)).state as DecimalType))/2
r e
e (
var Number pressureTrend = (pressure0avg -
n 0
pressure180avg) / 3.0
t )
PressureTrendValue.postUpdate(pressureTrend)
P
r }
if (pressureTrend > 1.2)
e
{ PressureTrendStatus.postUpdate(“QuickRise”)
s e
PressureTrendFlag.postUpdate(1)
s n
} else if (pressureTrend > 0.1) {
PressureTrendStatus.postUpdate(“SlowRise”) d
>
PressureTrendFlag.postUpdate(1) } else if (pressureTrend
< -1.2) {
m
PressureTrendStatus.postUpdate(“QuickFall”)
a
PressureTrendFlag.postUpdate(-1) } else if
x
(pressureTrend < -0.1) {
P
PressureTrendStatus.postUpdate(“SlowFall”)
r Abbiamo tutti i
PressureTrendFlag.postUpdate(-1) } else {
e dati che ci
s
s
P servono, quindi
)
r adesso
e vediamo come
s
{
s usarli per
/
u ottenere gli
/
s
r ultimi due
e parametri da
t
T
o presentare nel
r
r
e widget: la
e
n
d
descrizione delle
t
h
S previsioni e
t l’icona
e
a
t corrispondente.
M
u Per prima cosa
A
s
X definiamo le
.
M
p tabelle usate per
o le diverse con-
a
s
x versioni (Listato
t
P
r
U 3); l’operazione è
p
e effettuata ogni
d
s
s
a 10 minuti e non
t ci sono altri
u
e
r trigger basati su
(
e
“ item. Per definire
.
S
p degli array in
t
o
s
e OpenHAB
a occorre usare gli
t
d
U ArrayList, i quali
y
p
non sono array tradizionali ma, piuttosto, una classe
contenitore di Java (trovate i dettagli nei JavaDocs).
Vedremo negli esempi come devono essere usati
(Listato 4). L’equivalente informatico del regolo
Zambretti funziona aggiungendo (algebricamente) dei
parametri di correzione alla pressione barometrica
relativa misurata, per simulare lo spostamento dei
cursori del regolo. La tabella windCorr serve per la
correzione relativa alla direzione del vento usando la
convenzione a 16 punti della rosa dei venti; dividendo
l’angolo giro per 22°30’ si arriva a stimare i cosiddetti
mezzi venti, che sono gli stessi forniti dai servizi
metereologici on-line. Il regolo originale è sviluppato
per funzionare esclusivamente nell’emisfero nord, ma è
sufficiente girare di 180° la rosa dei venti nel caso le
previsioni siano effettuate nell’emisfero australe. Il numero intero calcolato è usato come indice per recuperare, dalla tabella, il valore di
correzione adatto. Attenzione che la variabile sia effettivamente di tipo int, altrimenti l’ArrayList non può es
Ð Listato 3
rule “Zambretti” when Time cron “0 0/10 * * * ?”
then val zambrettiText = newArrayList (
//Zambretti forecast text ‘Bel tempo stabile’, ‘Bel tempo’, ‘In miglioramento’, ‘Bello, in peggioramento’, ‘Bello, possibilità di rovesci’, ‘Abbastanza bello, in
miglioramento’, ‘Abbastanza bello, possibili rovesci mattutini’, ‘Abbastanza bello, leggeri rovesci’, ‘Rovesci, in miglioramento’, ‘Variabile’, ‘Abbastanza bello,
rovesci probabili’, ‘Piuttosto instabile, migliora sul tardi’, ‘Instabile, probabile miglioramento’, ‘Piovoso, schiarite a intervalli’, ‘Piovoso, in peggioramento’,
‘Variabile, qualche rovescio’, ‘Alternanza di nuvole e brevi schiarite’, ‘Alternanza di nuvole e rovesci a fine giornata’, ‘Alternanza di nuvole e qualche
rovescio’, ‘Veramente molto instabile’, ‘Occasionale pioggia, peggioramento’, ‘Pioggia a tratti, molto instabile’, ‘Frequenti rovesci’, ‘Pioggia, molto instabile’,

‘Temporalesco, in miglioramento’, ‘Temporalesco, molta pioggia’


)

val windCorr = newArrayList ( //pressure value correction with the wind direction 5.2, 4.2, 3.2,
1.05, -1.1, -3.15, -5.2, -8.35, -11.5, -9.4, -7.3, -5.25, -3.2, -1.15, 0.9, 3.05 )

val lutRising = newArrayList


( //Zambretti result in case of rising pressure //’A’, ‘B’, ‘B’, ‘C’, ‘F’, ‘G’, ‘I’, ‘J’, ‘L’, ‘M’, ‘M’, ‘Q’, ‘T’, ‘Y’
0 , 1, 1, 2, 5, 6, 8, 9, 11, 12, 12, 16, 19, 24 )

val lutFalling = newArrayList


( //Zambretti result in case of falling pressure //’B’, ‘D’, ‘H’, ‘O’, ‘R’, ‘U’, ‘V’, ‘X’, ‘X’, ‘Z’
1 , 3, 7, 14, 17, 20, 21, 23, 23, 25 )

val lutSteady = newArrayList


( //Zambretti result in case of steady pressure //’A’, ‘B’, ‘B’, ‘B’, ‘E’, ‘K’, ‘N’, ‘N’, ‘P’, ‘P’, ‘S’, ‘W’, ‘W’, ‘X’, ‘X’, ‘X’, ‘Z’
0, 1, 1, 1, 4, 10, 13, 13, 15, 15, 18, 22, 22, 23, 23, 23, 25 )