diff --git a/IOB-PI/std_vers/readParallela.py.new b/IOB-PI/std_vers/readParallela.py.new new file mode 100644 index 0000000..dd86b32 --- /dev/null +++ b/IOB-PI/std_vers/readParallela.py.new @@ -0,0 +1,774 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# readParallela v. 2.3 +# - single instance timer +# - invio multiplo x send eventi accodati +# - gestione segnali BLINKING +# - gestione INVERSIONE segnali cv 10-VII-2018 +# - gestione FILTRAGGIO segnali brevi cv 23-VII-2018 +# - (2.3) gestione 12 bit cv 14-I-2020 + +#--------------------------------------------------------------- +# levare locking +# timer semplificata +# GPIO global + + +import time +import sys + + +from datetime import datetime + +import urllib +import ConfigParser +import os, sys + +import logging +import logging.handlers +import threading +import Queue + +from array import * + +#-------------------------------------------------------------- + +# COSTANTI +MSGLEN = 9 +TIMEOUTSERIALE = 10 +MAXRETRY = 3 + +# numero campioni filtraggio segnale ballerino +MAX_COUNTER_BLINK = 10 + +PROGRAM_NAME ="ReadPar IOB-pi v.2.3" + +# DA FILE CONF +idxMacchina = "1001" +SAMPLETIME = 0.1 +TIMEOUTSHORT = (SAMPLETIME*20) +TIMEOUTLONG = (SAMPLETIME*600) +SENDURLTIME = 0.08 +NMAXSEND = 5 # numero massimo di invii per singolo ciclo di svuotamento + +# VAR +to_enable = False +to_short = TIMEOUTSHORT +to_long = TIMEOUTLONG +to_serial = TIMEOUTSERIALE +to_retry = MAXRETRY +errormsglen = 0 + +# VAR + +out_0 = 24 +out_1 = 26 + +in_0 = 11 +in_1 = 12 +in_2 = 13 +in_3 = 15 +in_4 = 16 +in_5 = 18 +in_6 = 22 +in_7 = 7 + +in_8 = 29 +in_9 = 31 +in_10 = 36 +in_11 = 32 + +# contatore: serve x match tra accoda ed invia x possibile controllo a posteriori... ogni volta che accodo incremento di 1, va da 0 a 9999 +cont = '0' + +# variabile stato online/offline della macchina +onLine = '1' + +# variabile stato seinding/waiting x la parte invio URL +sending = '0' + +# variabile stato timer thread busy +timer_busy = False + +# +# array per ingressi filtrati + +i_counters = array ( 'i',[0,0,0,0,0,0,0,0,0,0,0,0]) +B_blinking = array ( 'B',[0,0,0,0,0,0,0,0,0,0,0,0]) +B_previous = array ( 'B',[0,0,0,0,0,0,0,0,0,0,0,0]) +B_input = array ( 'B',[0,0,0,0,0,0,0,0,0,0,0,0]) +B_output = array ( 'B',[0,0,0,0,0,0,0,0,0,0,0,0]) + +B_inverting = array ( 'B',[0,0,0,0,0,0,0,0,0,0,0,0]) + +B_filter = array ( 'B',[0,0,0,0,0,0,0,0,0,0,0,0]) +B_filter_prev = array ( 'B',[0,0,0,0,0,0,0,0,0,0,0,0]) +B_temp = array ( 'B',[0,0,0,0,0,0,0,0,0,0,0,0]) +i_filter_counters = array ( 'i',[0,0,0,0,0,0,0,0,0,0,0,0]) + +#-------------------------------------------------------------- +# Gestione coda (condivisa) x registrazione eventi ed invio URL +#print "Creazione coda illimitata" + +Coda = Queue.Queue(0) + +#queueLock = threading.Lock() + +#--------------------------------------------------------------- +# lettura parallela +# ritorna il byte letto pulito ( due char hex ) + +def readParallelaFiltrata(): + + global in_0 + global in_1 + global in_2 + global in_3 + global in_4 + global in_5 + global in_6 + global in_7 + + global in_8 + global in_9 + global in_10 + global in_11 + + + global GPIO + + current = '' + + + try: + + if GPIO.input(in_0): + B_input[0] = 0 + else: + B_input[0] = 1 + + if GPIO.input(in_1): + B_input[1] = 0 + else: + B_input[1] = 1 + + if GPIO.input(in_2): + B_input[2] = 0 + else: + B_input[2] = 1 + + if GPIO.input(in_3): + B_input[3] = 0 + else: + B_input[3] = 1 + + if GPIO.input(in_4): + B_input[4] = 0 + else: + B_input[4] = 1 + + if GPIO.input(in_5): + B_input[5] = 0 + else: + B_input[5] = 1 + + if GPIO.input(in_6): + B_input[6] = 0 + else: + B_input[6] = 1 + + if GPIO.input(in_7): + B_input[7] = 0 + else: + B_input[7] = 1 + + + if GPIO.input(in_8): + B_input[8] = 0 + else: + B_input[8] = 1 + + if GPIO.input(in_9): + B_input[9] = 0 + else: + B_input[9] = 1 + + if GPIO.input(in_10): + B_input[10] = 0 + else: + B_input[10] = 1 + + if GPIO.input(in_11): + B_input[11] = 0 + else: + B_input[11] = 1 + + + + + + + #ciclo per ogni segnale + for i in xrange(12) : + # print (i) + + # v2.1 gestione inversione bit ingresso + + if ( B_inverting[i] == 1 ) : + if ( B_input[i] == 0 ) : + B_input[i] = 1 + else : + B_input[i] = 0 + + # v2.2 gestione filtro segnali brevi + + if ( B_filter[i] == 1 ) : + + # fronte 0 -> 1 + if ( B_input[i] == 1 ) and ( B_filter_prev [i] == 0 ) : + if ( i_filter_counters[i] == 0 ) : + # vero fronte 0 -> 1 + i_filter_counters[i] = MAX_COUNTER_FILTER + B_temp[i] = 0 # tengo l' ingresso a 0 + #logPro.info("START spike 0->1 on bit " + `i` ) + else : + # fine disturbo breve di uno stato 1 + i_filter_counters[i] = 0 + B_temp[i] = 1 # tengo l' ingresso a 1 + logPro.info("END spike 0->1 on bit " + `i` ) + + # stabile 1 -> 1 + if ( B_input[i] == 1 ) and ( B_filter_prev [i] == 1 ) : + if ( i_filter_counters[i] == 0 ) : + # segnale stabile a 1 + B_temp[i] = 1 # tengo l' ingresso a 1 + else : + # poco dopo il fronte + i_filter_counters[i] = i_filter_counters[i] - 1 + B_temp[i] = 0 # tengo l' ingresso a 0 + + # fronte 1 -> 0 + if ( B_input[i] == 0 ) and ( B_filter_prev [i] == 1 ) : + if ( i_filter_counters[i] == 0 ) : + # vero fronte 1 -> 0 + i_filter_counters[i] = MAX_COUNTER_FILTER + B_temp[i] = 1 # tengo l' ingresso a 1 + #logPro.info("START spike 1->0 on bit " + `i` ) + else : + # fine disturbo breve di uno stato 0 + i_filter_counters[i] = 0 + B_temp[i] = 0 # tengo l' ingresso a 0 + logPro.info("END spike 1->0 on bit " + `i` ) + + # stabile 0 -> 0 + if ( B_input[i] == 0 ) and ( B_filter_prev [i] == 0 ) : + if ( i_filter_counters[i] == 0 ) : + # segnale stabile a 0 + B_temp[i] = 0 # tengo l' ingresso a 0 + else : + # poco dopo il fronte + i_filter_counters[i] = i_filter_counters[i] - 1 + B_temp[i] = 1 # tengo l' ingresso a 1 + + B_filter_prev [i] = B_input[i] + B_input[i] = B_temp[i] + + # fine gestione filtro segnali brevi + + + # se non blinking, copia ingresso + if ( B_blinking[i] == 0 ) : + B_output[i] = B_input[i] + else: + # gestione segnale blinking + # se fronte del segnale + if ( B_previous[i] != B_input[i] ) : + B_previous[i] = B_input[i] + # se fronte di salita + if ( B_input[i] == 1 ) : + # subito uscita = 1 + B_output[i] = 1 + i_counters[i] = MAX_COUNTER_BLINK + #else : + # # loggo che ho rilevato un blink... + # logPro.info("Blink down on bit " + `i`) + else: + # no , segnale eguale a prima + # se input a 0 + if ( B_input[i] == 0 ) : + # E CONTEGGIO IN CORSO + if ( i_counters[i] > 0 ) : + i_counters[i] = i_counters[i] -1 + if ( i_counters[i] == 0 ) : + B_output[i] = 0 + logPro.info("END Blink on bit " + `i` ) + + #Rimettiamo insieme i bit + new_value = 0 + + if ( B_output[0] == 1 ) : + new_value = new_value + 1 + if ( B_output[1] == 1 ) : + new_value = new_value + 2 + if ( B_output[2] == 1 ) : + new_value = new_value + 4 + if ( B_output[3] == 1 ) : + new_value = new_value + 8 + if ( B_output[4] == 1 ) : + new_value = new_value + 16 + if ( B_output[5] == 1 ) : + new_value = new_value + 32 + if ( B_output[6] == 1 ) : + new_value = new_value + 64 + if ( B_output[7] == 1 ) : + new_value = new_value + 128 + + if ( B_output[8] == 1 ) : + new_value = new_value + 256 + if ( B_output[9] == 1 ) : + new_value = new_value + 512 + if ( B_output[10] == 1 ) : + new_value = new_value + 1024 + if ( B_output[11] == 1 ) : + new_value = new_value + 2048 + + + current = hex( new_value ).replace ( "0x" , "" ).upper() + + except: + pass + + return current + +#--------------------------------------------------------------- +#Funzione di scrittura su coda con try-except + +def accoda(): + + try: + dtEve = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')[:-3] + Coda.put(dtEve + '#' + value + '#' + cont) + + except Queue.Full: + logPro.error( "Queue full" + `dtEve` + '#' + `value` + '#' + `cont` ) + except: + logPro.error( "NETWORK:Errore http-no com rete-timeout" + url ) +# print "Url aforte" , url + + +#-------------------------------------------------------------- +# svuotaCoda x invio dati al server +def svuota_coda(): + + global onLine + global sending + global timer_busy + global NMAXSEND + + #print "start timer " + + if ( timer_busy == False ): + timer_busy = True + #print "start timer ok " + + try: + if not Coda.empty(): + #print "coda da svuotare!" + response = urllib.urlopen(URLALIVE) + answ = response.read() + if answ == 'OK': + #print "OK alive" + response2 = urllib.urlopen(URLENABLED + idxMacchina) + answ2 = response2.read() + if answ2 == 'OK': + # aggiorno stato ad online + if onLine == '0': + logPro.info("IOB ONLINE!") + #print("IOB ONLINE") + + onLine = '1' # imposto comunque online + else: + if onLine == '1': + logPro.error("IOB offline") + #print("IOB offline") + + onLine = '0' + else: + if onLine == '1': + logPro.error("Server offline") + #print("Server offline") + + onLine = '0' + + # ora verifico SE si possa inviare (ovvero sia online server e NON ci siano altri send attivi...) + if onLine == '1': + if sending == '0': + #segnalo che sono in sending! + sending = '1' + + # SAM 2016.12.23: modifica x invio FINO A nMaxSend ELEMENTI ad ogni ciclo di svuotamento + i = NMAXSEND + + while i >= 0: + if not Coda.empty(): + + # formatto dataOra corrente + dtCurr = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')[:-3] + + #prendo primo elemento dalla coda + resp = Coda.get() + + # recupero valori da elemento coda! + dtEve = resp.split("#")[0] + value = resp.split("#")[1] + cnt = resp.split("#")[2] + url = URLBASE + idxMacchina + URLADV1 + value + url = url + '&dtCurr=' + dtCurr + '&dtEve=' + dtEve + '&cnt=' + cnt + # CHIAMO URL + response3 = urllib.urlopen ( url ) + answ3 = response3.read() + #print(url) + + # log valore inviato! + logSnd.info( value + ' ['+ cnt +']' + ' R:' + answ3 ) + #print "Valore smaltito dalla coda" + + # tolgo 1 al contatore + i -= 1 + + # completato invio, riporto sending a zero! + sending = '0' + else: + logPro.info("WAIT active send to complete") + + else: + pass + + else: + pass + + except: + if onLine == '1': + logPro.error("Server Non raggiungibile") + #print "Non raggiungibile" + + onLine = '0' + +# in ogni caso + + timer_busy = False + #print "end timer ok" + + + #print "end timer " + + +#--------------------------------------------------------------- +# funzione timer thread +#--------------------------------------------------------------- +def do_every (interval, worker_func, iterations = 0): + if iterations != 1: + threading.Timer ( + interval, + do_every, [interval, worker_func, 0 if iterations == 0 else iterations-1] + ).start (); + + worker_func (); + +#--------------------------------------------------------------- +# gestione contatore +#--------------------------------------------------------------- +def contatore(): + + try: + global cont + ctr = int(cont) + ctr +=1 + ctr = ctr % 10000 # round robin 10000 eventi x track + cont = str(ctr) + except: + print("errore incremento contatore") + +#--------------------------------------------------------------- +# avvia porta parallela +#--------------------------------------------------------------- +def avviaParallela(): + + global in_0 + global in_1 + global in_2 + global in_3 + global in_4 + global in_5 + global in_6 + global in_7 + global in_8 + global in_9 + global in_10 + global in_11 + + global GPIO + + try: + + GPIO.setmode(GPIO.BOARD) + + GPIO.setwarnings(False) + + #GPIO.setup(out_0, GPIO.OUT) # output 0 + #GPIO.setup(out_1, GPIO.OUT) # output 1 + + GPIO.setup(in_0, GPIO.IN) # input 0 + GPIO.setup(in_1, GPIO.IN) # input 1 + GPIO.setup(in_2, GPIO.IN) # input 2 + GPIO.setup(in_3, GPIO.IN) # input 3 + GPIO.setup(in_4, GPIO.IN) # input 4 + GPIO.setup(in_5, GPIO.IN) # input 5 + GPIO.setup(in_6, GPIO.IN) # input 6 + GPIO.setup(in_7, GPIO.IN) # input 7 + GPIO.setup(in_8, GPIO.IN) # input 8 + GPIO.setup(in_9, GPIO.IN) # input 9 + GPIO.setup(in_10, GPIO.IN) # input 10 + GPIO.setup(in_11, GPIO.IN) # input 11 + + except: + print( "\n\n" + PROGRAM_NAME + " - Error 3 on RPi.GPIO ! \n\n") + sys.exit(1) + + + print( "\n\n" + PROGRAM_NAME + " - init ok \n\n") + + +#--------------------------------------------------------------- +#--------------------------------------------------------------- +# MAIN + +try: + config = ConfigParser.RawConfigParser() + config.read ( 'IOB.cfg' ) + + SAMPLETIME = config.getfloat ( 'time' , 'SAMPLETIME' ) + TIMEOUTSHORT = config.getfloat ( 'time' , 'TIMEOUTSHORT' ) + TIMEOUTLONG = config.getfloat ( 'time' , 'TIMEOUTLONG' ) + SENDURLTIME = config.getfloat ( 'time' , 'SENDURLTIME' ) + NMAXSEND = config.getint ( 'time' , 'NMAXSEND' ) + + idxMacchina = config.get ( 'id' , 'idxMacchina' ) + + + URLBASE = config.get ( 'web' , 'URLBASE' ) + URLENABLED = config.get('web' , 'URLENABLED') + URLALIVE = config.get ('web' , 'URLALIVE') + URLADV1 = config.get ( 'web' , 'URLADV1' ) + + LOGFILE = config.get ( 'log' , 'LOGFILE' ) + LOGLEVEL = config.get ( 'log' , 'LOGLEVEL' ) + + B_blinking[0] = config.getint ( 'blink' , 'bit0' ) + B_blinking[1] = config.getint ( 'blink' , 'bit1' ) + B_blinking[2] = config.getint ( 'blink' , 'bit2' ) + B_blinking[3] = config.getint ( 'blink' , 'bit3' ) + B_blinking[4] = config.getint ( 'blink' , 'bit4' ) + B_blinking[5] = config.getint ( 'blink' , 'bit5' ) + B_blinking[6] = config.getint ( 'blink' , 'bit6' ) + B_blinking[7] = config.getint ( 'blink' , 'bit7' ) + B_blinking[8] = config.getint ( 'blink' , 'bit8' ) + B_blinking[9] = config.getint ( 'blink' , 'bit9' ) + B_blinking[10] = config.getint ( 'blink' , 'bit10' ) + B_blinking[11] = config.getint ( 'blink' , 'bit11' ) + + MAX_COUNTER_BLINK = config.getint ( 'blink' , 'MAX_COUNTER_BLINK' ) + + # cv 2.1 se bit = 1 allora inverto segnale in ingresso... + + B_inverting[0] = config.getint ( 'invert' , 'bit0' ) + B_inverting[1] = config.getint ( 'invert' , 'bit1' ) + B_inverting[2] = config.getint ( 'invert' , 'bit2' ) + B_inverting[3] = config.getint ( 'invert' , 'bit3' ) + B_inverting[4] = config.getint ( 'invert' , 'bit4' ) + B_inverting[5] = config.getint ( 'invert' , 'bit5' ) + B_inverting[6] = config.getint ( 'invert' , 'bit6' ) + B_inverting[7] = config.getint ( 'invert' , 'bit7' ) + B_inverting[8] = config.getint ( 'invert' , 'bit8' ) + B_inverting[9] = config.getint ( 'invert' , 'bit9' ) + B_inverting[10] = config.getint ( 'invert' , 'bit10' ) + B_inverting[11] = config.getint ( 'invert' , 'bit11' ) + + # cv 2.2 se bit = 1 allora filtro segnali brevi ... + + B_filter[0] = config.getint ( 'filter' , 'bit0' ) + B_filter[1] = config.getint ( 'filter' , 'bit1' ) + B_filter[2] = config.getint ( 'filter' , 'bit2' ) + B_filter[3] = config.getint ( 'filter' , 'bit3' ) + B_filter[4] = config.getint ( 'filter' , 'bit4' ) + B_filter[5] = config.getint ( 'filter' , 'bit5' ) + B_filter[6] = config.getint ( 'filter' , 'bit6' ) + B_filter[7] = config.getint ( 'filter' , 'bit7' ) + B_filter[8] = config.getint ( 'filter' , 'bit8' ) + B_filter[9] = config.getint ( 'filter' , 'bit9' ) + B_filter[10] = config.getint ( 'filter' , 'bit10' ) + B_filter[11] = config.getint ( 'filter' , 'bit11' ) + + MAX_COUNTER_FILTER = config.getint ( 'filter' , 'MAX_COUNTER_FILTER' ) + + +except: + print "\n\n" + PROGRAM_NAME + ' - Error 4 - in config file ' 'IOB.cfg' + sys.exit(1) + +#-------------------------------------------- +# oggetto Logger +#-------------------------------------------- +try: + logging.basicConfig(level=logging.DEBUG, + format='%(asctime)s %(name)-8s %(levelname)-8s %(message)s', + datefmt='%Y-%m-%d %H:%M:%S', + filename=LOGFILE, + filemode='a' + ) + + # aggiungo 2 logger specifici x queue e send... + logQue = logging.getLogger('queue') + logSnd = logging.getLogger('sendUrl') + logPro = logging.getLogger('program') + +except: + # manda mail o simili - FARE!!! + print "LOG: Impossibile creare file log con nome " + print (LOGFILE) +#-------------------------------------------- + + +print "\n\n" + PROGRAM_NAME + "\n\n" + +global startstatus +startstatus = 1 + +if startstatus == 1: + logPro.info("Avvio Programma" + PROGRAM_NAME) + +## Verifica l'OS e di conseguenza carica il file relativo con metodo di lockfile appropriato + check singola istanza +if os.name == 'posix': + import unix +else: + import win + +logPro.info( "Start " + PROGRAM_NAME ) + + +# lettura file configurazione + +# [id] +# idxMacchina = 2001 +# [time] +# SAMPLETIME = 0.1 +# TIMEOUTSHORT = 200 +# TIMEOUTLONG = 6000 + + +print ( ' idxMacchina = %s' % ( idxMacchina ) ) +print ( ' SAMPLETIME = %4.2f' % ( SAMPLETIME ) ) +print ( ' TIMEOUTSHORT = %4.2f' % ( TIMEOUTSHORT ) ) +print ( ' TIMEOUTLONG = %4.2f' % ( TIMEOUTLONG ) ) +print ( ' SENDURLTIME = %4.2f' % ( SENDURLTIME ) ) +print ( ' URLBASE = %s' % ( URLBASE ) ) +print ( ' URLADV1 = %s' % ( URLADV1 ) ) +print ( ' LOGFILE = %s' % ( LOGFILE ) ) +print ( ' LOGLEVEL = %s' % ( LOGLEVEL ) ) + +# -sys.stdout.write ( 'idxMacchina ?' + idxMacchina + '\n') + +to_short = TIMEOUTSHORT +to_long = TIMEOUTLONG + + +#-------------------------------------------------------------- +# apertura parallela + +try: + import RPi.GPIO as GPIO +except RuntimeError: + print( "\n\n" + PROGRAM_NAME + " - Error 1 - you need superuser privileges") +except: + print( "\n\n" + PROGRAM_NAME + " - Error 2 - you need superuser privileges. USE 'sudo' to run your script\n\n") + sys.exit(1) + + +avviaParallela() + + +#-------------------------------------------------------------- +# MARCO: qui inserire avvio thread di "svuotaCoda" + +# avviaSvuotaCoda +#print "Avvia svuota coda" + +do_every ( SENDURLTIME , svuota_coda ); + +#--------------------------------------------------------------- +# ciclo forever and ever + +old = '' + +#print "Avvio ciclo" +logPro.info("Avvio loop principale") +while 1: + + try: + time.sleep (SAMPLETIME) + except: + logPro.info("First_SLEEP: errore attesa sampletime") + + # lettura dati da IOB + value = readParallelaFiltrata() + + if ( value != '' ) : + if value != old : + #loggo e invio dati + try: + logQue.info( value + ' ['+ cont +']') + errormsglen = 0 + accoda() + contatore() + except: + logPro.error("URLBROWSER: errore registrazione valore e accoda") + pass + #enable e reset timer + to_enable = True + to_short = TIMEOUTSHORT + to_long = TIMEOUTLONG + + old = value + + + # gestione timeout breve + if ( to_enable ) : + to_short = to_short - SAMPLETIME + if to_short <= 0: + #loggo e invio dati + try: + logQue.info( '>' + value + ' ['+ cont +']') + errormsglen = 0 + accoda() + contatore() + except: + logPro.error("URLBROWSER: errore registrazione valore e accoda TO_short") + pass + to_short = TIMEOUTSHORT + to_enable = False # dopo un colpo il timer breve viene disabilitato + to_long = TIMEOUTLONG + + # gestione timeout lungo + to_long = to_long - SAMPLETIME + if to_long <= 0: + #loggo e invio dati + try: + logQue.info( '>>' + value + ' ['+ cont +']') + errormsglen = 0 + accoda() + contatore() + except: + logPro.error("URLBROWSER: errore registrazione valore e accoda TO_long") + pass + to_long = TIMEOUTLONG diff --git a/IOB-PI/std_vers/readParallela.py.old b/IOB-PI/std_vers/readParallela.py.old new file mode 100644 index 0000000..f49e4f7 --- /dev/null +++ b/IOB-PI/std_vers/readParallela.py.old @@ -0,0 +1,706 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# readParallela v. 2.2 +# - single instance timer +# - invio multiplo x send eventi accodati +# - gestione segnali BLINKING +# - gestione INVERSIONE segnali cv 10-VII-2018 +# - gestione FILTRAGGIO segnali brevi cv 23-VII-2018 + +#--------------------------------------------------------------- +# levare locking +# timer semplificata +# GPIO global + + +import time +import sys + + +from datetime import datetime + +import urllib +import ConfigParser +import os, sys + +import logging +import logging.handlers +import threading +import Queue + +from array import * + +#-------------------------------------------------------------- + +# COSTANTI +MSGLEN = 9 +TIMEOUTSERIALE = 10 +MAXRETRY = 3 + +# numero campioni filtraggio segnale ballerino +MAX_COUNTER_BLINK = 10 + +PROGRAM_NAME ="ReadPar IOB-pi v.2.2" + +# DA FILE CONF +idxMacchina = "1001" +SAMPLETIME = 0.1 +TIMEOUTSHORT = (SAMPLETIME*20) +TIMEOUTLONG = (SAMPLETIME*600) +SENDURLTIME = 0.08 +NMAXSEND = 5 # numero massimo di invii per singolo ciclo di svuotamento + +# VAR +to_enable = False +to_short = TIMEOUTSHORT +to_long = TIMEOUTLONG +to_serial = TIMEOUTSERIALE +to_retry = MAXRETRY +errormsglen = 0 + +# VAR + +out_0 = 24 +out_1 = 26 + +in_0 = 11 +in_1 = 12 +in_2 = 13 +in_3 = 15 +in_4 = 16 +in_5 = 18 +in_6 = 22 +in_7 = 7 + +# contatore: serve x match tra accoda ed invia x possibile controllo a posteriori... ogni volta che accodo incremento di 1, va da 0 a 9999 +cont = '0' + +# variabile stato online/offline della macchina +onLine = '1' + +# variabile stato seinding/waiting x la parte invio URL +sending = '0' + +# variabile stato timer thread busy +timer_busy = False + +# +# array per ingressi filtrati + +i_counters = array ( 'i',[0,0,0,0,0,0,0,0]) +B_blinking = array ( 'B',[0,0,0,0,0,0,0,0]) +B_previous = array ( 'B',[0,0,0,0,0,0,0,0]) +B_input = array ( 'B',[0,0,0,0,0,0,0,0]) +B_output = array ( 'B',[0,0,0,0,0,0,0,0]) + +B_inverting = array ( 'B',[0,0,0,0,0,0,0,0]) + +B_filter = array ( 'B',[0,0,0,0,0,0,0,0]) +B_filter_prev = array ( 'B',[0,0,0,0,0,0,0,0]) +B_temp = array ( 'B',[0,0,0,0,0,0,0,0]) +i_filter_counters = array ( 'i',[0,0,0,0,0,0,0,0]) + +#-------------------------------------------------------------- +# Gestione coda (condivisa) x registrazione eventi ed invio URL +#print "Creazione coda illimitata" + +Coda = Queue.Queue(0) + +#queueLock = threading.Lock() + +#--------------------------------------------------------------- +# lettura parallela +# ritorna il byte letto pulito ( due char hex ) + +def readParallelaFiltrata(): + + global in_0 + global in_1 + global in_2 + global in_3 + global in_4 + global in_5 + global in_6 + global in_7 + + global GPIO + + current = '' + + + try: + + if GPIO.input(in_0): + B_input[0] = 0 + else: + B_input[0] = 1 + + if GPIO.input(in_1): + B_input[1] = 0 + else: + B_input[1] = 1 + + if GPIO.input(in_2): + B_input[2] = 0 + else: + B_input[2] = 1 + + if GPIO.input(in_3): + B_input[3] = 0 + else: + B_input[3] = 1 + + if GPIO.input(in_4): + B_input[4] = 0 + else: + B_input[4] = 1 + + if GPIO.input(in_5): + B_input[5] = 0 + else: + B_input[5] = 1 + + if GPIO.input(in_6): + B_input[6] = 0 + else: + B_input[6] = 1 + + if GPIO.input(in_7): + B_input[7] = 0 + else: + B_input[7] = 1 + + #ciclo per ogni segnale + for i in xrange(8) : + # print (i) + + # v2.1 gestione inversione bit ingresso + + if ( B_inverting[i] == 1 ) : + if ( B_input[i] == 0 ) : + B_input[i] = 1 + else : + B_input[i] = 0 + + # v2.2 gestione filtro segnali brevi + + if ( B_filter[i] == 1 ) : + + # fronte 0 -> 1 + if ( B_input[i] == 1 ) and ( B_filter_prev [i] == 0 ) : + if ( i_filter_counters[i] == 0 ) : + # vero fronte 0 -> 1 + i_filter_counters[i] = MAX_COUNTER_FILTER + B_temp[i] = 0 # tengo l' ingresso a 0 + #logPro.info("START spike 0->1 on bit " + `i` ) + else : + # fine disturbo breve di uno stato 1 + i_filter_counters[i] = 0 + B_temp[i] = 1 # tengo l' ingresso a 1 + logPro.info("END spike 0->1 on bit " + `i` ) + + # stabile 1 -> 1 + if ( B_input[i] == 1 ) and ( B_filter_prev [i] == 1 ) : + if ( i_filter_counters[i] == 0 ) : + # segnale stabile a 1 + B_temp[i] = 1 # tengo l' ingresso a 1 + else : + # poco dopo il fronte + i_filter_counters[i] = i_filter_counters[i] - 1 + B_temp[i] = 0 # tengo l' ingresso a 0 + + # fronte 1 -> 0 + if ( B_input[i] == 0 ) and ( B_filter_prev [i] == 1 ) : + if ( i_filter_counters[i] == 0 ) : + # vero fronte 1 -> 0 + i_filter_counters[i] = MAX_COUNTER_FILTER + B_temp[i] = 1 # tengo l' ingresso a 1 + #logPro.info("START spike 1->0 on bit " + `i` ) + else : + # fine disturbo breve di uno stato 0 + i_filter_counters[i] = 0 + B_temp[i] = 0 # tengo l' ingresso a 0 + logPro.info("END spike 1->0 on bit " + `i` ) + + # stabile 0 -> 0 + if ( B_input[i] == 0 ) and ( B_filter_prev [i] == 0 ) : + if ( i_filter_counters[i] == 0 ) : + # segnale stabile a 0 + B_temp[i] = 0 # tengo l' ingresso a 0 + else : + # poco dopo il fronte + i_filter_counters[i] = i_filter_counters[i] - 1 + B_temp[i] = 1 # tengo l' ingresso a 1 + + B_filter_prev [i] = B_input[i] + B_input[i] = B_temp[i] + + # fine gestione filtro segnali brevi + + + # se non blinking, copia ingresso + if ( B_blinking[i] == 0 ) : + B_output[i] = B_input[i] + else: + # gestione segnale blinking + # se fronte del segnale + if ( B_previous[i] != B_input[i] ) : + B_previous[i] = B_input[i] + # se fronte di salita + if ( B_input[i] == 1 ) : + # subito uscita = 1 + B_output[i] = 1 + i_counters[i] = MAX_COUNTER_BLINK + #else : + # # loggo che ho rilevato un blink... + # logPro.info("Blink down on bit " + `i`) + else: + # no , segnale eguale a prima + # se input a 0 + if ( B_input[i] == 0 ) : + # E CONTEGGIO IN CORSO + if ( i_counters[i] > 0 ) : + i_counters[i] = i_counters[i] -1 + if ( i_counters[i] == 0 ) : + B_output[i] = 0 + logPro.info("END Blink on bit " + `i` ) + + #Rimettiamo insieme i bit + new_value = 0 + + if ( B_output[0] == 1 ) : + new_value = new_value + 1 + if ( B_output[1] == 1 ) : + new_value = new_value + 2 + if ( B_output[2] == 1 ) : + new_value = new_value + 4 + if ( B_output[3] == 1 ) : + new_value = new_value + 8 + if ( B_output[4] == 1 ) : + new_value = new_value + 16 + if ( B_output[5] == 1 ) : + new_value = new_value + 32 + if ( B_output[6] == 1 ) : + new_value = new_value + 64 + if ( B_output[7] == 1 ) : + new_value = new_value + 128 + + current = hex( new_value ).replace ( "0x" , "" ).upper() + + except: + pass + + return current + +#--------------------------------------------------------------- +#Funzione di scrittura su coda con try-except + +def accoda(): + + try: + dtEve = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')[:-3] + Coda.put(dtEve + '#' + value + '#' + cont) + + except Queue.Full: + logPro.error( "Queue full" + `dtEve` + '#' + `value` + '#' + `cont` ) + except: + logPro.error( "NETWORK:Errore http-no com rete-timeout" + url ) +# print "Url aforte" , url + + +#-------------------------------------------------------------- +# svuotaCoda x invio dati al server +def svuota_coda(): + + global onLine + global sending + global timer_busy + global NMAXSEND + + #print "start timer " + + if ( timer_busy == False ): + timer_busy = True + #print "start timer ok " + + try: + if not Coda.empty(): + #print "coda da svuotare!" + response = urllib.urlopen(URLALIVE) + answ = response.read() + if answ == 'OK': + #print "OK alive" + response2 = urllib.urlopen(URLENABLED + idxMacchina) + answ2 = response2.read() + if answ2 == 'OK': + # aggiorno stato ad online + if onLine == '0': + logPro.info("IOB ONLINE!") + #print("IOB ONLINE") + + onLine = '1' # imposto comunque online + else: + if onLine == '1': + logPro.error("IOB offline") + #print("IOB offline") + + onLine = '0' + else: + if onLine == '1': + logPro.error("Server offline") + #print("Server offline") + + onLine = '0' + + # ora verifico SE si possa inviare (ovvero sia online server e NON ci siano altri send attivi...) + if onLine == '1': + if sending == '0': + #segnalo che sono in sending! + sending = '1' + + # SAM 2016.12.23: modifica x invio FINO A nMaxSend ELEMENTI ad ogni ciclo di svuotamento + i = NMAXSEND + + while i >= 0: + if not Coda.empty(): + + # formatto dataOra corrente + dtCurr = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')[:-3] + + #prendo primo elemento dalla coda + resp = Coda.get() + + # recupero valori da elemento coda! + dtEve = resp.split("#")[0] + value = resp.split("#")[1] + cnt = resp.split("#")[2] + url = URLBASE + idxMacchina + URLADV1 + value + url = url + '&dtCurr=' + dtCurr + '&dtEve=' + dtEve + '&cnt=' + cnt + # CHIAMO URL + response3 = urllib.urlopen ( url ) + answ3 = response3.read() + #print(url) + + # log valore inviato! + logSnd.info( value + ' ['+ cnt +']' + ' R:' + answ3 ) + #print "Valore smaltito dalla coda" + + # tolgo 1 al contatore + i -= 1 + + # completato invio, riporto sending a zero! + sending = '0' + else: + logPro.info("WAIT active send to complete") + + else: + pass + + else: + pass + + except: + if onLine == '1': + logPro.error("Server Non raggiungibile") + #print "Non raggiungibile" + + onLine = '0' + +# in ogni caso + + timer_busy = False + #print "end timer ok" + + + #print "end timer " + + +#--------------------------------------------------------------- +# funzione timer thread +#--------------------------------------------------------------- +def do_every (interval, worker_func, iterations = 0): + if iterations != 1: + threading.Timer ( + interval, + do_every, [interval, worker_func, 0 if iterations == 0 else iterations-1] + ).start (); + + worker_func (); + +#--------------------------------------------------------------- +# gestione contatore +#--------------------------------------------------------------- +def contatore(): + + try: + global cont + ctr = int(cont) + ctr +=1 + ctr = ctr % 10000 # round robin 10000 eventi x track + cont = str(ctr) + except: + print("errore incremento contatore") + +#--------------------------------------------------------------- +# avvia porta parallela +#--------------------------------------------------------------- +def avviaParallela(): + + global in_0 + global in_1 + global in_2 + global in_3 + global in_4 + global in_5 + global in_6 + global in_7 + + global GPIO + + try: + + GPIO.setmode(GPIO.BOARD) + + GPIO.setwarnings(False) + + #GPIO.setup(out_0, GPIO.OUT) # output 0 + #GPIO.setup(out_1, GPIO.OUT) # output 1 + + GPIO.setup(in_0, GPIO.IN) # input 0 + GPIO.setup(in_1, GPIO.IN) # input 1 + GPIO.setup(in_2, GPIO.IN) # input 2 + GPIO.setup(in_3, GPIO.IN) # input 3 + GPIO.setup(in_4, GPIO.IN) # input 4 + GPIO.setup(in_5, GPIO.IN) # input 5 + GPIO.setup(in_6, GPIO.IN) # input 6 + GPIO.setup(in_7, GPIO.IN) # input 7 + + except: + print( "\n\n" + PROGRAM_NAME + " - Error 3 on RPi.GPIO ! \n\n") + sys.exit(1) + + + print( "\n\n" + PROGRAM_NAME + " - init ok \n\n") + + +#--------------------------------------------------------------- +#--------------------------------------------------------------- +# MAIN + +try: + config = ConfigParser.RawConfigParser() + config.read ( 'IOB.cfg' ) + + SAMPLETIME = config.getfloat ( 'time' , 'SAMPLETIME' ) + TIMEOUTSHORT = config.getfloat ( 'time' , 'TIMEOUTSHORT' ) + TIMEOUTLONG = config.getfloat ( 'time' , 'TIMEOUTLONG' ) + SENDURLTIME = config.getfloat ( 'time' , 'SENDURLTIME' ) + NMAXSEND = config.getint ( 'time' , 'NMAXSEND' ) + + idxMacchina = config.get ( 'id' , 'idxMacchina' ) + + + URLBASE = config.get ( 'web' , 'URLBASE' ) + URLENABLED = config.get('web' , 'URLENABLED') + URLALIVE = config.get ('web' , 'URLALIVE') + URLADV1 = config.get ( 'web' , 'URLADV1' ) + + LOGFILE = config.get ( 'log' , 'LOGFILE' ) + LOGLEVEL = config.get ( 'log' , 'LOGLEVEL' ) + + B_blinking[0] = config.getint ( 'blink' , 'bit0' ) + B_blinking[1] = config.getint ( 'blink' , 'bit1' ) + B_blinking[2] = config.getint ( 'blink' , 'bit2' ) + B_blinking[3] = config.getint ( 'blink' , 'bit3' ) + B_blinking[4] = config.getint ( 'blink' , 'bit4' ) + B_blinking[5] = config.getint ( 'blink' , 'bit5' ) + B_blinking[6] = config.getint ( 'blink' , 'bit6' ) + B_blinking[7] = config.getint ( 'blink' , 'bit7' ) + + MAX_COUNTER_BLINK = config.getint ( 'blink' , 'MAX_COUNTER_BLINK' ) + + # cv 2.1 se bit = 1 allora inverto segnale in ingresso... + + B_inverting[0] = config.getint ( 'invert' , 'bit0' ) + B_inverting[1] = config.getint ( 'invert' , 'bit1' ) + B_inverting[2] = config.getint ( 'invert' , 'bit2' ) + B_inverting[3] = config.getint ( 'invert' , 'bit3' ) + B_inverting[4] = config.getint ( 'invert' , 'bit4' ) + B_inverting[5] = config.getint ( 'invert' , 'bit5' ) + B_inverting[6] = config.getint ( 'invert' , 'bit6' ) + B_inverting[7] = config.getint ( 'invert' , 'bit7' ) + + # cv 2.2 se bit = 1 allora filtro segnali brevi ... + + B_filter[0] = config.getint ( 'filter' , 'bit0' ) + B_filter[1] = config.getint ( 'filter' , 'bit1' ) + B_filter[2] = config.getint ( 'filter' , 'bit2' ) + B_filter[3] = config.getint ( 'filter' , 'bit3' ) + B_filter[4] = config.getint ( 'filter' , 'bit4' ) + B_filter[5] = config.getint ( 'filter' , 'bit5' ) + B_filter[6] = config.getint ( 'filter' , 'bit6' ) + B_filter[7] = config.getint ( 'filter' , 'bit7' ) + + MAX_COUNTER_FILTER = config.getint ( 'filter' , 'MAX_COUNTER_FILTER' ) + + +except: + print "\n\n" + PROGRAM_NAME + ' - Error 4 - in config file ' 'IOB.cfg' + sys.exit(1) + +#-------------------------------------------- +# oggetto Logger +#-------------------------------------------- +try: + logging.basicConfig(level=logging.DEBUG, + format='%(asctime)s %(name)-8s %(levelname)-8s %(message)s', + datefmt='%Y-%m-%d %H:%M:%S', + filename=LOGFILE, + filemode='a' + ) + + # aggiungo 2 logger specifici x queue e send... + logQue = logging.getLogger('queue') + logSnd = logging.getLogger('sendUrl') + logPro = logging.getLogger('program') + +except: + # manda mail o simili - FARE!!! + print "LOG: Impossibile creare file log con nome " + print (LOGFILE) +#-------------------------------------------- + + +print "\n\n" + PROGRAM_NAME + "\n\n" + +global startstatus +startstatus = 1 + +if startstatus == 1: + logPro.info("Avvio Programma" + PROGRAM_NAME) + +## Verifica l'OS e di conseguenza carica il file relativo con metodo di lockfile appropriato + check singola istanza +if os.name == 'posix': + import unix +else: + import win + +logPro.info( "Start " + PROGRAM_NAME ) + + +# lettura file configurazione + +# [id] +# idxMacchina = 2001 +# [time] +# SAMPLETIME = 0.1 +# TIMEOUTSHORT = 200 +# TIMEOUTLONG = 6000 + + +print ( ' idxMacchina = %s' % ( idxMacchina ) ) +print ( ' SAMPLETIME = %4.2f' % ( SAMPLETIME ) ) +print ( ' TIMEOUTSHORT = %4.2f' % ( TIMEOUTSHORT ) ) +print ( ' TIMEOUTLONG = %4.2f' % ( TIMEOUTLONG ) ) +print ( ' SENDURLTIME = %4.2f' % ( SENDURLTIME ) ) +print ( ' URLBASE = %s' % ( URLBASE ) ) +print ( ' URLADV1 = %s' % ( URLADV1 ) ) +print ( ' LOGFILE = %s' % ( LOGFILE ) ) +print ( ' LOGLEVEL = %s' % ( LOGLEVEL ) ) + +# -sys.stdout.write ( 'idxMacchina ?' + idxMacchina + '\n') + +to_short = TIMEOUTSHORT +to_long = TIMEOUTLONG + + +#-------------------------------------------------------------- +# apertura parallela + +try: + import RPi.GPIO as GPIO +except RuntimeError: + print( "\n\n" + PROGRAM_NAME + " - Error 1 - you need superuser privileges") +except: + print( "\n\n" + PROGRAM_NAME + " - Error 2 - you need superuser privileges. USE 'sudo' to run your script\n\n") + sys.exit(1) + + +avviaParallela() + + +#-------------------------------------------------------------- +# MARCO: qui inserire avvio thread di "svuotaCoda" + +# avviaSvuotaCoda +#print "Avvia svuota coda" + +do_every ( SENDURLTIME , svuota_coda ); + +#--------------------------------------------------------------- +# ciclo forever and ever + +old = '' + +#print "Avvio ciclo" +logPro.info("Avvio loop principale") +while 1: + + try: + time.sleep (SAMPLETIME) + except: + logPro.info("First_SLEEP: errore attesa sampletime") + + # lettura dati da IOB + value = readParallelaFiltrata() + + if ( value != '' ) : + if value != old : + #loggo e invio dati + try: + logQue.info( value + ' ['+ cont +']') + errormsglen = 0 + accoda() + contatore() + except: + logPro.error("URLBROWSER: errore registrazione valore e accoda") + pass + #enable e reset timer + to_enable = True + to_short = TIMEOUTSHORT + to_long = TIMEOUTLONG + + old = value + + + # gestione timeout breve + if ( to_enable ) : + to_short = to_short - SAMPLETIME + if to_short <= 0: + #loggo e invio dati + try: + logQue.info( '>' + value + ' ['+ cont +']') + errormsglen = 0 + accoda() + contatore() + except: + logPro.error("URLBROWSER: errore registrazione valore e accoda TO_short") + pass + to_short = TIMEOUTSHORT + to_enable = False # dopo un colpo il timer breve viene disabilitato + to_long = TIMEOUTLONG + + # gestione timeout lungo + to_long = to_long - SAMPLETIME + if to_long <= 0: + #loggo e invio dati + try: + logQue.info( '>>' + value + ' ['+ cont +']') + errormsglen = 0 + accoda() + contatore() + except: + logPro.error("URLBROWSER: errore registrazione valore e accoda TO_long") + pass + to_long = TIMEOUTLONG