Differenze tra le versioni di "Termostato 2.0"

Da raspibo.
Jump to navigation Jump to search
Riga 119: Riga 119:
 
Per tenere traccia del momento in cui viene lanciata la lettura:
 
Per tenere traccia del momento in cui viene lanciata la lettura:
 
<source lang=python>
 
<source lang=python>
root@termostato:~/termostato# cat /root/termostato/salva_tempo.py
 
 
#!/usr/bin/python
 
#!/usr/bin/python
 
import os
 
import os

Versione delle 18:48, 18 gen 2016

Premessa

Mentre Raspibo nasceva, appena comprato il mio primo Raspberry Pi ho pensato di iniziare a sperimentare con i sensori di temperatura 1 wire.

Mi ero immaginato di creare un piccolo server casalingo su cui far girare server web e altri servizi, nel frattempo ho iniziato a sperimentare per usare il mio nuovo Raspberry come termostato con risultati interessanti.

Nel frattempo ho iniziato a frequentare questo nuovo gruppo ed ho imparato tante cose nuove, la tecnologia ha fatto passi avanti.

Il termostato funzionava cosi' bene che manometterlo per farci girare su altri esperimenti potenzialmente bloccanti non era piu' il caso, ho acquistato e messo in servizio altri Raspberry ed i lavori non si sono mai completati.

Percio' ho pubblicato su questo wiki il progetto Termostato, che ha riscosso un discreto successo, anche ora ogni tanto vengo contattato per vari motivi, qualcuno ha bisogno di chiarimenti, qualcuno mi chiede info e via dicendo.

Ora ho deciso di rimettere mano ed iniziare ex novo tenendo conto anche delle esigenze di chi mi ha contattato in questi anni, renderne piu' flessibile il funzionamento e in generale cercare di miglioralo ed ammodernarlo.

Obiettivi

  • Implementare un sistema flessibile e "facilmente" modificabile(ampliabile).
  • Rendere la presentazione semplice, e allo stesso tempo graficamente gradevole.
  • Aumentare l'affidabilita' del sistema con il monitoraggio dei procesi
  • Semplificare il controllo del sistema con un display lcd per la visualizzazione dei dati rilevati
  • Permettere il controllo da remoto in modo semplice e sicuro

Non tutti gli obiettivi sono facili da realizzare, o anche solo da testare, l'importante e' porre le basi per renderne la realizzazione non troppo complessa cercando di predisporre gia' i software(in parte anche l'hardware) nel modo migliore.

Vecchie soluzioni

Una soluzione un po' particolare adottata nella prima versione del progetto e' l'adozione di redis come "database", in realta' non si tratta di un db, ma di un data structure store, used as database, cache and message broker. I motivi della scelta erano la volonta' di provare ad untilizzare un db nosql ed esplorare le possibilita' di questo progetto.

Negli anni si e' dimostrato affidabile ed ho pensato di continuare su questa strada, per aggingere nuove funzionalita' ho dovuto studiare un po' ed ho scoperto nuove ed interessanti fetaures che avevo tralasciato.

Nuovi esperimenti

Termostato utilizza principalmente script in bash per la memorizzazione dei dati e la gestione del rele della caldaia, ma pensare di espandere il codice con questo linguaggio e' difficile.

Ho pensato di provare Python che non ho mai usato per piu' di qualche riga, ma mi risulta ben fornito di moduli per gestire una infinita' di situazioni, al momento tutto il codice di controllo e' scritto con questo linguaggio.

Per la parte web ho deciso di utilizzare un cms gia' pronto, si chiama Grav non utilizza db, ma e' tutto basato su file, non è fatto per utilizzare direttamente php e le pagine di interazione con l'utente mi hanno fatto penare un po' per trovare una soluzione, ma alla fine ce l'ho fatta e sono soddisfatto del risultato.

Ho conosciuto Monit usato da Paolo nel progetto Rmap per la verifica di funzionalità dei processi ed il loro ripristino in caso di down, ho voluto utilizzarlo anche io perchè è uno strumento interessante.

Nelle nuove release di Debian systemd ha preso il posto di init, non mi ci sono buttato a capofitto, ma ho iniziato a cercare di capire come funziona.

Per il controllo da remoto ho voluto provare a realizzare un bot con telegram, così da non dover aprire porte sul modem.

Redis

Vediamo ora in dettaglio Redis. Questo db è il centro di comunicazione e memorizzazione dei dati, passano su redis i dati di temperatura, le schedulazioni ed i dati dei sensori di input ed output (es: rele).

Redis permette di gestire più database (predefiniti 16), per selezionare un db basta specificarlo tra i parametri di connessione, ho anche previsto l'inserimento come parametro del nome del server.

Ho previsto già negli script di poter passare come parametro il db di redis (indicato da un numero), questo per permettere la gestione di più sessioni/istanze di regolazione della temperatura, un caso abbastanza comune potrebbe essere rappresentato da un impianto con una sola caldia, ma elettrovalvole distribuite su varie stanze con possibilità di aprire o chiudere il flusso di acqua calda.

Redis permette anche di sottoscrivere un canale ovvero mettere un processo in ascolto in attesa di notizie ovvero la variazione di valore di una variabile, l'ho utilizzato per pilotare il rele evitando di interrogare periodicamente il db.

Struttura dati

Ho creato una lista per ogni sensore, in linea di massima ogni stanza ha un sensore ed ogni sensore ha un id univoco (se utilizziamo sensori 1wire), perciò tramite parametro passato ad uno script python inserisco una lettura indicando l'id del sensore da leggere e una etichetta alfanumerica che nella maggioranza dei casi rappresenta una stanza.

Lo script di inserimento dati è abbastanza semplice:

#!/usr/bin/python
import os
import glob
import time
import redis
import sys

if len(sys.argv) > 2:
        db_host=sys.argv[1]
        db_id=sys.argv[2]

else:
        print "Attenzione: lo script va lanciato con due argomenti!  "
        print "Lancia lo script: " + sys.argv[0] + "<db_host (es: 127.0.0.1)> <id database (es:0)>"
        db_host='termostato_m'
        db_id=0
        print "Utilizzo i parametri di default: " + db_host + " " + str(db_id)
 
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
 
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + sys.argv[4])[0]
device_file = device_folder + '/w1_slave'
 
def read_temp_raw():
    f = open(device_file, 'r')
    lines = f.readlines()
    f.close()
    return lines
 
def read_temp():
    lines = read_temp_raw()
    while lines[0].strip()[-3:] != 'YES':
        time.sleep(0.2)
        lines = read_temp_raw()
    equals_pos = lines[1].find('t=')
    if equals_pos != -1:
        temp_string = lines[1][equals_pos+2:]
        temp_c = float(temp_string) / 1000.0
	if temp_c < 50:
        	return temp_c
	
print(device_folder + " " + str(read_temp()))	
r = redis.StrictRedis(host=db_host, port=6379, db=db_id,password='Termostato_2.0')
r.rpush(sys.argv[3],float(read_temp()))

Lo script viene lanciato schedulato da crontab con una periodicità di 5 minuti del mio caso.

/root/termostato/salva_temp.py <indirizzo_server_redis> <id_db-redis> <tag/stanza> <idsensore>

esempio:

/root/termostato/salva_temp.py termostato_m 0 cucina 28-000004056005

Per ogni sensore va lanciato un comando in cui presumibilmente cambieranno il tag che indica la stanza e l'id del sensore.

Per tenere traccia del momento in cui viene lanciata la lettura:

#!/usr/bin/python
import os
import glob
import time
import redis
import sys

if len(sys.argv) > 2:
        db_host=sys.argv[1]
        db_id=sys.argv[2]
	
else:
        print "Attenzione: lo script va lanciato con due argomenti!  "
        print "Lancia lo script: " + sys.argv[0] + "<db_host (es: 127.0.0.1)> <id database (es:0)>" 
	db_host='termostato_m'
	db_id=0
	print "Utilizzo i parametri di default: " + db_host + " " + str(db_id)

r = redis.StrictRedis(host=db_host, port=6379, db=db_id,password='Termostato_2.0')
r.rpush("timestamp",time.strftime("%s"))

Si lancia semplicemente cosi:

/root/termostato/salva_tempo.py termostato_m 0

Riferimenti

  • cms grav link alla procedura di installazione - user termoadmin - password Termostato_2.0
  • Monit user termoadmin - password Termostato_2.0