www.errorediridondanzaciclicodotcom

  • HOME
  • DALLAS MANAGE 2
  • BACK P.P.

  • IL CODICE INTEGRATO

    Qui sotto il codice utilizzato in qualsiasi script dove vogliamo leggere le temperature registrate dalle Dallas.
    Definisco una classe valida per i sensori, definisco dei metodi e, alla fine creo le istanze.
    
    class D18B20:
      def __init__(self, sens_name):
        self.name = sens_name 
    		
      def setdir(self):
        with open('sens.json', 'r') as file:
          data = json.load(file)
          sensor=self.name
          for key, value in data.items():
    	      if value == sensor:
    		    device_file= key + '/w1_slave'
    		    return device_file
    
      def read_temp_raw(self):
        device_file=self.setdir()
        try:
          f = open(device_file, 'r')
          lines = f.readlines()
          f.close()
          return lines
        except:
          lines = str("error")
          return lines
    
      def read_temp(self):
        lines = self.read_temp_raw()
        
        #se lines non è = 'error'
        if lines != str("error"): 
          
          #individua la lettere "t"
          char_pos=lines[1].find('t=')
          
          #se c'e' YES alla fine legge normalmente e ritorna temp_c    
          if lines[0].strip()[-3:]=='YES': 
            tstring=lines[1][char_pos+2:] 
            temp_c = float(tstring)/1000
            temp_c = round(temp_c, 1)
            
            #85 indica un errore di lettura (es. solo la VCC è staccata)
            if temp_c != 85 or temp_c < 60: 
    	        return temp_c
            else:
    	        time.sleep(2)
    	        char_pos=lines[1].find('t=')
    	        tstring=lines[1][char_pos+2:] 
    	        temp_c = float(tstring)/1000
    	        temp_c=round(temp_c, 1)
    	        return "temp not valid"
          
          #se non c'e' YES (NO) ritorna 88.8 (la dir esiste ancora ma c'e' NO) 
          else: 
            return 88.8
      
      #se lines = error (la dir e' sparita e read_temp_raw() non trova la dir e ritorna error), ritorna 99.9
        else:  
          return 99.9
    
    tempshower=D18B20("temp4")
    tempshower=tempshower.read_temp()
    print(tempshower)
    
    Partiamo dalla fine, cioè da quella parte di codice che definisce il sensore e legge la temperatura:

    tempshower=D18B20("temp4")

    tempshower è l'istanza (l'oggetto) della classe D18B20 che creiamo.
    Questa classe prevede (lo vediamo meglio dopo) che alla creazione di ogni istanza si specifichi il nome, per questo mettiamo tra virgolette il nome che assegneremo. Questo nome deve essere, in questo caso, quello che abbiamo assegnato al sensore "X" con lo script esterno.

    Ora che abbiamo un'istanza, possiamo eseguire i metodi (le funzioni) che questa classe prevede.

    tempshower=tempshower.read_temp()

    Qui è come se alla macchina dicessimo: tempshower è uguale al risultato della funzione read_temp() eseguita sull'istanza tempshower della classe D18B20. Ovviamente questo risultato sarà un valore di temperatura che alla fine di questo blocco di codice stampiamo (print(tempshower)) per vederlo. In genere il "print" serve per la verifica del codice, nel mio script il risultato sarà invece utilizzato in altre parti e la visualizzazione avverrá nella finestra di output finale

    Sotto è riportato il metodo che ho "definito" nella mia classe:

    def read_temp(self):

    lines = self.read_temp_raw()
    ...................

    return temp_c

    Riporto solo le prime due righe e il valore di ritorno che ottengo da questo metodo. Il "self" tra le parentesi serve a collegare questo metodo all'istanza creata.
    Questo metodo legge a sua volta una stringa ottenuta da un metodo precedente (le linee del file che contiene i valori di temperatura) e, dopo alcuni check ed elaborazioni "ritorna" il valore di temperatura che ci serve.
    Come detto, utilizza un altro metodo appartenente alla stessa classe: read_temp_raw() che, con davanti self, si lega anch'esso all'istanza creata.

    Qui sotto il blocco di codice che definisce il metodo di cui sopra:

    def read_temp_raw(self):

    device_file=self.setdir()

    try:

    f = open(device_file, 'r')
    lines = f.readlines()
    f.close()
    return lines

    Ancora una volta, il metodo prenderà come input il risultato di un metodo precedente e che sarà device_file. Questa classe ha tre metodi che possono anche essere ridotti ma per mia scelta preferisco così per una migliore lettura.
    Dopo il richiamo del metodo si vede solo la parte di try (except si vede nel codice completo) che, con il sistema classico, apre il file specificato dalla directory di device_file e ne ritorna le linee.

    Per ultimo, il metodo setdir():

    def setdir(self):

    with open('sens.json', 'r') as file:

    data = json.load(file)
    sensor=self.name
    for key, value in data.items():

    if value == sensor:

    device_file= key + '/w1_slave'
    return device_file

    Questo metodo serve a definire la directory del sensore che stiamo leggendo.
    Apre il file .json che lo script esterno ha generato (nell'esempio non si vede il path ma è buona prassi metterlo insieme a questi script).
    La variabile data conterrà quanto letto (json.load) dal file.
    Assegno poi alla variabile value il "nome" dell'istanza (quel nome che deve essere uguale a quanto specificato nello script iniziale).
    Eseguo poi un'iterazione su data.items cioè le coppie del dizionario che ha creato il file .json. Per iterare le coppie è importante specificare .items altrimenti si può specificare solo .key o solo .values.
    In ogni passaggio faccio poi il controllo: se il nome del sensore (sensor) è uguale ad uno dei values del dict, device_file sarà uguale alla corrispondente key (la directory completa della Dallas) più il nome del file (w1_slave).
    Ritorno infine questa stringa come device_file, cioè la stringa che servirà da input al metodo successivo.

    Per ultimo, sempre procedendo a ritroso, si può vedere la definizione di classe:

    class D18B20:

    def __init__(self, sens_name):

    self.name = sens_name

    Il primo metodo, detto costruttore, contiene un parametro che dovrà essere obbligatoriamente specificato quando si crea un nuova istanza, il nome del sensore legato all'istanza.
    Subito dopo specifico che il nome che assegno alla variabile "self.name" è proprio questo parametro. Questa variabile viene poi utilizzata nei metodi successivi.

    Qualora avessi 100 Dallas da monitorare, il lavoro sarebbe solo di assegnare i nomi a ciascuna con lo script esterno e, nei rispettivi script dove voglio leggere i valori creare le istanze di ogni sensore. Il tutto viene infine semplificato se la definizione di classe la metto in un modulo a sè stante (uno script isolato) che richiamo semplicemente dove voglio leggere le temperature con import "modulo".
    In questo script sarà sufficiente (avendo messo import "modulo") scriver, per esempio:
    temp_shower = "modulo importato".D18B20("temp_shower") ed il resto come sopra.

    ANCHE QUESTO E' IL MAGICO PYTHON.