UNA SVEGLIA PARLANTE PERSONALIZZATA CHE TI DICE LA TEMPERATURA

Qui descrivo una sveglia che ti da delle informazioni sulla temperatura e se sta piovendo. Nell'autunno 2018 ho riscritto tutto il programma e migliorato la gestione della CPU.

HARDWARE


Il programma è stato scritto in python3 utilizzando pygame come modulo GUI.

1. PREPARAZIONE SCHEDA SD
Download Dell'ultima versione di raspbian Stretch (attenzione, con una versione successiva a Stretch ho avuto problemi con e-speak, come confermato anche dal web), configurazione con boot grafico, abilitazione ssh, espansione filesystem, sudo apt-get update, sudo apt-get dist-upgrade.

2. INSTALLAZIONE DRIVER PER TOUCHSCREEN

Il touchscreen della lilliput viene fornito, a richiesta, con una scheda sd con pre-installato wheezy ed i driver per il funzionamento. L'unico problema è che non si può aggiornare questa sd, c'è la possibilità che sia necessario rifare l'installazione dei driver. Per essere più libero, personalmente, ho voluto installare separatamente i driver.

Il touchscreen 10" è forse sovradimensionato per l'uso come sveglia ma l'ho scelto per eventuali sviluppi ulteriori.
Finora sta funzionando bene, solo si deve premere lo schermo con una certa pressione (sarà perchè siamo abituati agli schermi resistivi?). L'assistenza della lilliput è veramente ok, sono stati competenti e disponibili. L'unico appunto è rivolto all'assenza di istruzioni che dovrebbero accompagnare il prodotto.

Questi sono i passi per fare funzionare il touchscreen:

sudo apt-get install libx11-dev
sudo apt-get install libext-dev (probabilmente vi dirà nessun pacchetto trovato ma non importa)
sudo apt-get install libxi-dev
sudo apt-get install x11proto-input-dev (il passo precedente dovrebbe avere già installato questo pacchetto)


si entra nel Desktop: cd Desktop

si scarica qui l'applicazione di calibrazione:

wget http://github.com/downloads/tias/xinput_calibrator/xinput_calibrator.0.7.5.tar.gz

si scompatta:

tar xvzf xinput_calibrator.0.7.5.tar.gz

ora abbiamo la dir xinput_calibrator.0.7.5 sul Desktop, accediamo:

cd xinput_calibrator.0.7.5/

e compiliamo il software:

./configure
make
sudo make install

A questo punto il touchscreen non funziona ancora, si deve calibrare e, ovviamente, se si vuole ritrovarlo funzionante ad ogni avvio, rendere permanente la calibrazione.
Tra le "preferences" del raspberry trovate: Calibrate Touchscreen.
Apritelo e compariranno delle croci di centraggio che dovrete premere. Consiglio di utilizzare il pennino per una maggiore precisione.
La prima (o le prime) volta il primo centraggio risulterà completamente sbagliato (166 al posto di 3999 come primo di quattro numeri), non preoccupatevi e rifate la calibrazione. Alla fine si aprirà il terminale e vedrete a metà circa scritto: Per rendere permanete la calibrazione.... Non chiudetela, vi servirà a breve.

Ora si deve creare una directory, un file e scrivere dentro i parametri di configurazione che avete sul terminale.

prima si crea la directory:

sudo mkdir /etc/X11/xorg.conf.d

poi si crea e si edita il file:

sudo nano /etc/X11/xorg.conf.d/24-input.conf

Il numero 24 è un numero che può variare, nel mio caso di questo schermo della lilliput ho trovato che era questo, in giro ho visto ad esempio mettere 01.
Nel file dovete copiare quanto è scritto sul terminale che ho detto di lasciare aperto, cioè:

Section "InputClass"
Identifier "calibration"
MatchProduct "eGalax Inc. USB TouchController"
Option "Calibration" "xxxx xxxx xxxx xxxx"
Option "SwapAxes" "1"
EndSection


al posto delle "x" andranno i numeri specifici della vostra calibrazione. La riga 'Option SwapAxes 1' potrebbe non esserci tra le vostre righe della calibrazione, aggiungetela.

3. INSTALLAZIONE DI UNO SCREENSAVER

Nell'Uso quotidiano questa sveglia dovrebbe essere in prossimità del letto. Il problema conosciuto del raspberry è che non funziona con l'hdmi il power management, cioè il monitor non si spegne mai, anche se nero rimane la backlight.
Per ovviare a ciò ho installato vcgencmd, un tool che, trasferendo i comandi alla "VideoCore", permette di disabilitare l'HDMI direttamente. In pratica si tratta di mettere nello script la funzione vcgencmd display_power 1 per abilitarlo e vcgencmd display_power 0 per disabilitarlo.
Collegato al Pir, al rilevamento del movimento lo schermo si accende. Dopo un tot di tempo lo schermo si disabilita, lasciando lo screen buio.

4. GESTIONE SUONO E SPEECH

Quando la sveglia oltre la musica vi dirà di svegliarvi e la temperatura, avete bisogno che sia installato un programma di "speech".
Innanzitutto settiamo il suono. Sul raspi il suono è gestito da alsaplayer che dovrebbe essere già installato nelle ultime release. Sul terminale scrivete alsa e date due volte il tab, se vedrete alcuni pacchetti con dentro la parola alsa, è ok, altrimenti si dovrà installare (in questo tutorial considero già ok il pacchetto).

Prima avviate questa interfaccia hard-soft (audio hal: Hardware abstraction layer):

sudo modprobe snd-bcm2835

questo comando andrà dato ad ogni cambio di output tra hdmi e analogica, dopo il reboot. Potrebbe essere necessario rendere permanente questo comando (nel mio caso no). Se lo fosse dovete aggiungere snd_modprobe 2835 alla fine di /etc/modules.
a questo punto installate espeak:

sudo apt-get update
sudo apt-get install mplayer espeak (se non avete alsa, aggiungete alsa-libs)

provate espeak con:

espeak "write what you would hear"

dovreste udire il suono delle parole dall'uscita hdmi.

Per il volume potete scrivere sul terminale alsamixer e vi comparirà un'interfaccia in cui c'è un livello che potete alzare e confermare semplicemente con exit.

Prima di spiegare alcune cose su espeak parlerò dell'uscita audio.

L'audio di default del raspi è auto cioè manda l'audio su hdmi o analog automaticamente a seconda di quale device è collegato al boot. Tuttavia il raspy non può avere due uscite contemporaneamente, per questo si deve configurare l'uscita desiderata nel caso ad esempio si utilizzi un monitor hdmi ma si voglia l'audio su jack.
Per ottenere ciò si deve scrivere sul terminale:

sudo amixer cset numid=3 "n"

dove n=0 auto, n=1 analog, n=2 hdmi

dopo il reboot (necessario) dovete ridare il
sudo modprobe snd-bcm2835

questa parte è importante qualora voleste mettere delle casse vicino al cuscino invece di avere l'audio in uscita sul monitor.

Espeak funziona così:

qui di seguito l'istruzione che verrà eseguita al momento della sveglia per fare parlare espeak:

cmd = 'espeak -ven+f2 --stdout "{0}" 2>/dev/null -a 50 -s 130 | aplay'.format(text)

En significa che parlerà in inglese. Ho provato l'italiano, in tre varianti ma sembra una tedesca che parla in italiano. Preferisco l'inglese ed ho scelto la voce 2 (f2). Una parte è necessaria per funzionare con il raspi ("{0}" 2>/dev/null).
Quando ho avviato le prime volte espeak sul raspi mi si interrompeva dopo tot secondi e la voce era gracchiante. Ho risolto mettendo nell'istruzione --stdout e due parametri a ed s seguiti da "|aplay".
Il parametro a è il volume che nel mio caso ho settato a 50. Il parametro s sono le battute per minuto che determinano la velocità della parlata. Il (text) è ciò che deve dire espeak.

if int(u) >= 0 and int(u)!=1.0:
text = "hi alby it's time to wake up the temperature outside is"+ str(u) + "degrees _: the temperature inside is"+ str(v) + "degrees"
elif int(u) == 1.0:
text = "hi alby it's time to wake up the temperature outside is"+ str(u) + "degree _: the temperature inside is"+ str(v) + "degrees"
else:
text = "hi alby it's time to wake up the temperature outside is"+ str(u) + "degrees below zero _: the temperature inside is"+ str(v) + "degrees"
cmd = 'espeak -ven+f2 --stdout "{0}" 2>/dev/null -a 50 -s 130 | aplay'.format(text)

U è la temperatura esterna che si deve verificare se è sotto o sopra lo 0 in quanto espeak non legge il segno meno. I due caratteri _: Servono a mettere un pò di pausa nella parlata. Se la temperatura è di un grado dirà degree e non degrees. V è la temperatura interna.

IL CODICE

import os.path, sys, datetime, time, glob
import pygame, random #pygame.font, pygame.event, pygame.draw, string
import threading
import RPi.GPIO as gpio
import psutil
from subprocess import call

#per abilitare KEYDOWN
from pygame.locals import *

#inizializza il clock come istanza per usare il tick nel lampeggio
clock = pygame.time.Clock()

#funzione per settare i pin del pi con il numero del processore (modo BCM)
gpio.setmode(gpio.BCM)
pygame.init()

#caricare nello script le ore e minuti attuali
#togliere i secondi e microsecondi per il match della sveglia con
#l'ora attuale che deve limitarsi ai minuti
time_now = datetime.datetime.now()
time_now = time_now.replace(second=0, microsecond=0)
time_now = time_now.strftime("%H:%M")

#inizializzare le variabili temperature e rain
temp1 = 0
temp2 = 0
rain_sen = 0

#leggere dalle dallas
base_dir = '/sys/bus/w1/devices/'
try:
device1_folder = glob.glob(base_dir + '28*')[1]
device1_file = device1_folder + '/w1_slave'
except:
device1_file = 'no file'
try:
device2_folder = glob.glob(base_dir + '28*')[0]
device2_file = device2_folder + '/w1_slave'
except:
device2_file = 'no file'

#info per adattare il display ad ogni monitor
infoScreen = pygame.display.Info()
SCW = infoScreen.current_w
SCH = infoScreen.current_h
SCW = 1024
SCH = 600
#unita' di misura relativa al monitor
Pw=int(SCW/100)
H_half=int(SCH/2)

screen = pygame.display.set_mode((SCW, SCH), FULLSCREEN).NOFRAME)

bg = pygame.Surface(screen.get_size())
bg = bg.convert()
bg.fill((0,0,40))

font = pygame.font.Font("/usr/share/fonts/truetype/digital-7mono.ttf", (Pw*23))
font1 = pygame.font.Font("/usr/share/fonts/truetype/digital-7mono.ttf", (Pw*12))
font2 = pygame.font.Font("/usr/share/fonts/truetype/digital-7.ttf", (Pw*5))
font3 = pygame.font.Font("/usr/share/fonts/truetype/digital-7.ttf", (Pw*3))
font4 = pygame.font.SysFont("arial", (Pw*2))
font5 = pygame.font.SysFont("arial", (Pw*4))
#ritardo per attivare lo screensaver
DELAY= 40

#prepara i disegni del lampeggio della sveglia
transColor = pygame.Color(0,0,0)
Imga=pygame.image.load('/home/pi/ClockAlarm/Images/icon_alarmR.bmp').convert()
Imga.set_colorkey(transColor)
Imga= pygame.transform.smoothscale(Imga, (100,100))
Imgb=pygame.image.load('/home/pi/ClockAlarm/Images/icon_alarm.bmp').convert()
Imgb.set_colorkey(transColor)
Imgb = pygame.transform.smoothscale(Imgb, (100,100))

#funzione per disattivare screensaver
##def saver():
pir_pin = 18
gpio.setup(pir_pin, gpio.IN)
saver_on=False
work_time=time.time()

#funzione per riattivare schermo
def MonOn():
call("vcgencmd display_power 1", shell=True)

#funzione per disattivare schermo
def MonOff():
call("vcgencmd display_power 0", shell=True)

#legge la temperatura dela cpu
def read_temp_cpu():
f = open('/sys/class/thermal/thermal_zone0/temp', 'r')
lines = f.read().splitlines()
lines=lines[0]
temp= float(lines)/1000
temp=int(temp)
f.close
return temp

#legge i dati grezzi dai file delle temps
def read_temp1_file():
try:
f = open(device1_file, 'r')
lines = f.readlines()
f.close
return lines
except:
lines=str("error")
return lines

def read_temp2_file():
try:
f = open(device2_file, 'r')
lines = f.readlines()
f.close
return lines
except:
lines=str("error")
return lines

#legge e converte in stringhe i dati di temp1
def read_temp1():
lines = read_temp1_file()
if lines != str('error') or lines[0].strip()[-3:] == 'YES':
t_pos = lines[1].find('t')
if lines[0].strip()[-3:] == 'YES':
temp1_string = lines[1][t_pos +2:]
temp1 = float(temp1_string)/1000
temp1 = round(temp1, 1)
if temp1 != 85:
return temp1
else:
time.sleep(2)
t_pos = lines[1].find('t')
temp1_string = lines[1][t_pos +2:]
temp1 = float(temp1_string)/1000
temp1 = round(temp1, 1)
return temp1
else:
return 'error1'
else:
return 'no dallas'

#legge e converte in stringhe i dati di temp2
def read_temp2():
lines = read_temp2_file()
if lines != str('error') or lines[0].strip()[-3:] == 'YES':
t_pos = lines[1].find('t')
if lines[0].strip()[-3:] == 'YES':
temp2_string = lines[1][t_pos +2:]
temp2 = float(temp2_string)/1000
temp2 = round(temp2, 1)
if temp2 != 85:
return temp2
else:
time.sleep(2)
t_pos = lines[1].find('t')
temp2_string = lines[1][t_pos +2:]
temp2 = float(temp2_string)/1000
temp2 = round(temp2, 1)
return temp2
else:
return 'error2'
else:
return 'no dallas'

#legge dal sensore di pioggia e restituisce il valore della resistenza
def get_rain():
gpio.setup(23, gpio.IN)
state = gpio.input(23)
if state == 0: #raining
rain_sen = 1
else: #drought
rain_sen = 0
time.sleep(1)
return rain_sen

#legge dal file dove e' memorizzata l'ora della sveglia
alarm_setted = open("/home/pi/ClockAlarm/textalm.txt","r")
for line in alarm_setted.readlines():
list=[line[0],line[1], line[3], line[4]]
Ha=(list[0]+list[1])
Ma=(list[2]+list[3])
Ha=int(Ha)
Ma=int(Ma)
alarm_setted.close()

#prende i valori letti nel file e li rende disponibili come ora allarme
alarm_time = datetime.time(Ha, Ma, 0)
alarm_time = alarm_time.strftime("%H:%M")

#legge lo stato, on/off, della sveglia al riavvio
askrestart = open("/home/pi/ClockAlarm/buttonask.txt","r")
lineaskres=askrestart.readlines()
askrestart.close()
k_status = (lineaskres[0][:])

#funzione per fare il riavvio della sveglia
def restart_program():
python = sys.executable
os.execl(python, python, * sys.argv)

#classe di python per mantenere attivo il thread del check sveglia
class Alarm(threading.Thread):
def __init__(self, Ha, Ma):
super(Alarm, self).__init__()
self.keep_running = True
def run(self):
try:
while self.keep_running:
if time_now == alarm_time and almon==True:
if(datetime.datetime.today().weekday())==0:
pygame.mixer.music.load('/home/pi/ClockAlarm/1.wav')
elif(datetime.datetime.today().weekday())==1:
pygame.mixer.music.load('/home/pi/ClockAlarm/2.wav')
elif(datetime.datetime.today().weekday())==2:
pygame.mixer.music.load('/home/pi/ClockAlarm/3.wav')
elif(datetime.datetime.today().weekday())==3:
pygame.mixer.music.load('/home/pi/ClockAlarm/4.wav')
elif(datetime.datetime.today().weekday())==4:
pygame.mixer.music.load('/home/pi/ClockAlarm/5.wav')
elif(datetime.datetime.today().weekday())==5:
pygame.mixer.music.load('/home/pi/ClockAlarm/6.wav')
elif(datetime.datetime.today().weekday())==6:
pygame.mixer.music.load('/home/pi/ClockAlarm/7.wav')

temp1=read_temp1()
temp2=read_temp2()
# pygame.mouse.set_pos((random.choice(range(600)), random.choice(range(600))))
MonOn()
time.sleep(5)
pygame.mixer.music.play(0)
time.sleep(12)
pygame.mixer.music.fadeout(4000)
time.sleep(4)
text=''
if rain_sen == 0:
if temp1 >= 0 and temp1 != 1.0:
text = "wake up alberto the temperature outside is"+ str(temp1) + "degrees _: the temperature inside is"+ str(temp2) + "degrees"
elif temp1 == 1.0:
text = "wake up alberto the temperature outside is"+ str(temp1) + "degree _: the temperature inside is"+ str(temp2) + "degrees"
else:
text = "wake up alberto the temperature outside is"+ str(temp1) + "degrees below zero _: the temperature inside is"+ str(temp2) + "degrees"
if rain_sen == 1:
if temp1 >= 0 and temp1 != 1.0:
text = "wake up alberto _: it's raining and the temperature outside is"+ str(temp1) + "degrees _: the temperature inside is"+ str(temp2) + "degrees"
elif temp1 == 1.0:
text = "wake up alberto _: probably it's snowing and the temperature outside is"+ str(temp1) + "degree _: the temperature inside is"+ str(temp2) + "degrees"
else:
text = "wake up alberto _: it's snowing and the temperature outside is"+ str(temp1) + "degrees below zero _: the temperature inside is"+ str(temp2) + "degrees"
cmd = 'espeak -ven+f2 --stdout "{0}" 2>/dev/null -a 50 -s 130 | aplay'.format(text)
os.system(cmd)
pygame.mixer.music.play(0)
return
except Exception as e:
print(e)
time.sleep(0.1)
def just_die(self):
#stoppa musica
pygame.mixer.music.stop()
#attende un tot di secondi
time.sleep(30)
#riavvia programma per fare ripartire il Thread dell'allarme
restart_program()
return

#classe di threading per la funzione di lampeggio sveglia
class BlinkAlarm(threading.Thread):
def __init__(self):
super(BlinkAlarm, self).__init__()
self.keep_running = True

def run(self):
while self.keep_running:
clock.tick(1)
Blitt=pygame.Rect(60,20,100,100)
screen.blit(Imgb, (60,20))
pygame.display.update(Blitt)
time.sleep(0.1)
screen.blit(Imga, (60,20))
pygame.display.update(Blitt)

#funzione per il corretto uso tastiera numpad
def get_key():
while 1:
event = pygame.event.poll()
if event.type == KEYDOWN and event.key != 300:
if (event.key >= 0x100 and event.key <= 0x109):
return event.key - 0xD0
elif (event.key == 271):
return 13
else:
return event.key
else:
pass

#funzione per disegnare box per modifica ora sveglia
def display_box(screen, message):

fontobject = pygame.font.Font(None,48)
#questo rect serve per il bkspace ed e' piu' piccolo
pygame.draw.rect(screen, (0,0,40),(Pw*85, Pw*25, Pw*5,Pw*4), 0)
#questo e' il rect con bordo e testo per immettere valori
pygame.draw.rect(screen, (0,255,255),(Pw*80, Pw*25, Pw*13,Pw*5), 1)
if len(message) != 0:
screen.blit(fontobject.render(message, 1, (0,255,255)), (Pw*80, Pw*25))
pygame.display.flip()

#funzione per immettere ora sveglia
def ask(screen, question):
current_string = []
display_box(screen, question +": " +"".join(current_string))

while 1:
inkey = get_key()
if inkey == K_BACKSPACE:
current_string = current_string[0:-1]
elif inkey == K_RETURN:
break
elif inkey:
current_string.append(chr(inkey))
display_box(screen, question +": " +"".join(current_string))
return "".join(current_string)

#funzione per disegnare box per modifica minuti sveglia
def display_box1(screen, message):

fontobject = pygame.font.Font(None,48)
#questo rect serve per il bkspace ed e' piu' piccolo
pygame.draw.rect(screen, (0,0,40),(Pw*87, Pw*30, Pw*5,Pw*4), 0)
#questo e' il rect con bordo e testo per immettere valori
pygame.draw.rect(screen, (0,255,255),(Pw*80, Pw*30, Pw*13,Pw*5), 1)
if len(message) != 0:
screen.blit(fontobject.render(message, 1, (0,255,255)),(Pw*80, Pw*30))
pygame.display.flip()

#funzione per immettere minuti sveglia
def ask1(screen, question):

pygame.font.init()
current_string = []
display_box1(screen, question +": " +"".join(current_string))

while 1:
inkey = get_key()
if inkey == K_BACKSPACE:
current_string = current_string[0:-1]
elif inkey == K_RETURN:
break
elif inkey:
current_string.append(chr(inkey))
display_box1(screen, question +": " +"".join(current_string))
return "".join(current_string)

#Image load
def load_image(file):
surface = pygame.image.load(file).convert()
return surface

#classe per pulsanti
class Button():
x=0
y=0
def __init__(self,Img,x,y, a,b):
transColor = pygame.Color(0,0,0)
image = load_image('/home/pi/ClockAlarm/Images/'+Img).convert()
image.set_colorkey(transColor)
image = pygame.transform.smoothscale(image, (a,b))
self.image = image
self.rect = self.image.get_rect()
self.bdh = screen.blit(self.image, (x,y))
def setCords(self,x,y):
self.rect.topleft = x,y
def pressed(self,mouse):
if mouse[0] > self.rect.topleft[0]:
if mouse[1] > self.rect.topleft[1]:
if mouse[0] < self.rect.bottomright[0]:
if mouse[1] < self.rect.bottomright[1]:
return True
else: return False
else: return False
else: return False
else: return False

#crea istanza di Alarm e la lancia (parte solo all'avvio o al restart!)
almon=False
alarm = Alarm(Ha,Ma)
alarm.start()

#legge all-'avvio se il pulsante e' on od off
askrestart = open("/home/pi/ClockAlarm/buttonask.txt","r")
lineaskres=askrestart.readlines()
askrestart.close()
k = (lineaskres[0][:])

Img='buttonstop.bmp'
buttonStop=Button(Img, (SCW/2)-(Pw*12), (Pw*3), (Pw*24), (Pw*4))
buttonStop.setCords((SCW/2)-(Pw*12), (Pw*3))

Img='buttonon.bmp'
buttonOn=Button(Img, 250, 150, 100,100)

Img='buttonoff.bmp'
buttonOff=Button(Img, 150, 150, 120,120)

#disegna l'ora
time_text = font.render("%s" % time_now, True, (0,255,255))
time_textRect = time_text.get_rect()
time_textRect.centerx = screen.get_rect().centerx
time_textRect.centery = screen.get_rect().centery - (Pw*11)

done=False

########################################################################################
#ciclo principale
while done==False:

#disegna il background
screen.blit(bg, (0,0))

#ottiene e disegna l'ora attuale
time_now = datetime.datetime.now()
time_now = time_now.replace(second=0, microsecond=0)
time_now = time_now.strftime("%H:%M")
time_text = font.render("%s" % time_now, True, (0,255,255))
screen.blit(time_text,time_textRect)

#carattere per il simbolo dei gradi da utilizzare dopo
t=chr(176)

#disegna la sveglia
alm_text = font1.render("%s" % alarm_time, True, (0,255,255))
alm_textRect = alm_text.get_rect()
alm_textRect.centerx = screen.get_rect().centerx
alm_textRect.centery = screen.get_rect().centery + (Pw*6)
screen.blit(alm_text,alm_textRect)

#disegna ogni ciclo i pulsanti sotto
Img='iconquit.png'
buttonQuit=Button(Img, Pw, (Pw*54), Pw*4, Pw*4)
buttonQuit.setCords(Pw,(Pw*54))
Img='buttonstop.bmp'
buttonStop=Button(Img, (SCW/2)-(Pw*12), (Pw*3), (Pw*24), (Pw*4))
buttonStop.setCords((SCW/2)-(Pw*12), (Pw*3))
Img='buttonset.bmp'
buttonSet=Button(Img, (Pw*6), ((H_half)+(Pw*1)), (Pw*10), (Pw*10))
buttonSet.setCords((Pw*6), ((H_half)+(Pw*1)))

#mette in ciclo la lettura del sensore pioggia
rain_sen = get_rain()

#disegna la nuvoletta se il sensore legge acqua
if rain_sen==1:
Img='icon_rain.bmp'
iconRain=Button(Img, (Pw*77), ((H_half)+(Pw*15)), (Pw*10), (Pw*10))

#ottiene le temperature
temp1=read_temp1()
temp2=read_temp2()

#disegna le temperature
temp1_text = font2.render("t out: %s" %temp1, True, (0,255,255))
temp1_textRect = temp1_text.get_rect()
temp1_textRect.centerx = screen.get_rect().centerx -(Pw*30)
temp1_textRect.centery = screen.get_rect().centery + (Pw*20)
screen.blit(temp1_text,temp1_textRect)
symb_t=font5.render("%s" %t, True, (0,255,255))
symb_tRect = symb_t.get_rect()
symb_tRect.centerx = screen.get_rect().centerx -(Pw*18.5)
symb_tRect.centery = screen.get_rect().centery + (Pw*20)
screen.blit(symb_t, symb_tRect)

temp2_text = font2.render("t IN: %s" %temp2, True, (0,255,255))
temp2_textRect = temp2_text.get_rect()
temp2_textRect.centerx = screen.get_rect().centerx +(Pw*1)
temp2_textRect.centery = screen.get_rect().centery + (Pw*20)
screen.blit(temp2_text,temp2_textRect)
symb_t=font5.render("%s" %t, True, (0,255,255))
symb_tRect = symb_t.get_rect()
symb_tRect.centerx = screen.get_rect().centerx +(Pw*10.3)
symb_tRect.centery = screen.get_rect().centery + (Pw*20)
screen.blit(symb_t, symb_tRect)

#se suona la sveglia compare un'icona
if time_now == alarm_time and almon==True:
blink=BlinkAlarm()
blink.start()
## Img='icon_alarmR.bmp'
## buttonAlm=Button(Img, Pw*6, Pw*2, Pw*10,Pw*10)

#rileva il movimento del pir per uscire dal screensaver e spengere allarme
if gpio.input(pir_pin):
work_time = time.time()
sys.stdout.flush()
if saver_on:
saver_on = False
MonOn()
if time_now == alarm_time and almon==True:
alarm.just_die()
else:
if not saver_on and time.time() > (work_time + DELAY):
saver_on = True
MonOff()
time.sleep(1)

#ottiene la percentuale di cpu
cpu_perc = int(psutil.cpu_percent())
cpu_perc = font3.render("cpu %% %s%%" %cpu_perc, True, (0,255,255))
cpu_percRect = cpu_perc.get_rect()
cpu_percRect.centerx = screen.get_rect().centerx +(Pw*40)
cpu_percRect.centery = screen.get_rect().centery - (Pw*20)
screen.blit(cpu_perc,cpu_percRect)

#disegna la temperatura cpu letta dalla funzione
temp=read_temp_cpu()
cpu_temp = font3.render("cpu T. %s" %temp, True, (0,255,255))
symb_t=font4.render("%s" %t, True, (0,255,255))
cpu_tempRect = cpu_temp.get_rect()
cpu_tempRect.centerx = screen.get_rect().centerx +(Pw*39.4)
cpu_tempRect.centery = screen.get_rect().centery - (Pw*15)
symb_tRect = symb_t.get_rect()
symb_tRect.centerx = screen.get_rect().centerx +(Pw*45.1)
symb_tRect.centery = screen.get_rect().centery - (Pw*15.1)
screen.blit(cpu_temp,cpu_tempRect)
screen.blit(symb_t, symb_tRect)

#controlla il parametro k scritto nel file e disegna l'icona memorizzata
if k=="no":
Img='buttonoff.bmp'
buttonOff=Button(Img, (Pw*6), ((H_half)-(Pw*14.5)), (Pw*10), (Pw*10))
buttonOff.setCords((Pw*6), ((H_half)-(Pw*14.5)))
almon=False

if k=="on":
Img='buttonon.bmp'
buttonOn=Button(Img, (Pw*6), ((H_half)-(Pw*14.5)), (Pw*10), (Pw*10))
buttonOn.setCords((Pw*6), ((H_half)-(Pw*14.5)))
almon=True

#ciclo eventi
for event in pygame.event.get():

if event.type == pygame.QUIT:
done=True

if event.type == pygame.MOUSEBUTTONUP:
mouse = pygame.mouse.get_pos()

#per uscire dal monitor in standby con una pressione sul mouse (se clikko -vedi sopra- e se...)
if saver_on:
work_time = time.time()
#sys.stdout.flush()
time.sleep(0.1)
saver_on = False
MonOn()
#se premuto il quit chiude il ciclo ed esce
if buttonQuit.pressed(mouse):
done=True

#se premuto set, modifica ora sveglia
if buttonSet.pressed(mouse):
f = open("/home/pi/ClockAlarm/textalm.txt","w")
f.write((ask(screen, "hh")))
f.write(" ")
f.write((ask1(screen, "mm")))
f.close()
restart_program()

#spegne la sveglia alla pressione del pulsante
if buttonStop.pressed(mouse):
alarm.just_die()

#cambia lo stato alarm on od off ad ogni pressione
if buttonOff.pressed(mouse):
Img='buttonon.bmp'
buttonOn=Button(Img, (Pw*6), ((H_half)-(Pw*14.5)), (Pw*10), (Pw*10))
almon=True
askrestart = open("/home/pi/ClockAlarm/buttonask.txt","w")
askrestart.write(str("on"))
askrestart.close()
restart_program()

if buttonOn.pressed(mouse):
Img='buttonoff.bmp'
buttonOff=Button(Img, (Pw*6), ((H_half)-(Pw*14.5)), (Pw*10), (Pw*10))
almon=False
askrestart = open("/home/pi/ClockAlarm/buttonask.txt","w")
askrestart.write(str("no"))
askrestart.close()
restart_program()

pygame.display.update()
time.sleep(0.2)
pygame.display.quit()
pygame.quit()
#per uccidere il programma completamente quando si esce con quit (altrimenti rimane in background)
cmd = 'killall python3'
os.system(cmd)
sys.exit()


Qui sotto gli screenshot del risultato finale (prima della sveglia).

Ora possiamo passare alla configurazione del web server. Vediamo a pagina due:

pagina 2 del talking alarm clock on the web