Files

531 lines
12 KiB
Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
# readParallela v. 1.8
# versione estetica di Carlo + single instance timer
#---------------------------------------------------------------
# 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
#--------------------------------------------------------------
# COSTANTI
MSGLEN = 9
TIMEOUTSERIALE = 10
MAXRETRY = 3
PROGRAM_NAME ="ReadPar IOB-pi v.1.8"
# DA FILE CONF
idxMacchina = "1001"
SAMPLETIME = 0.1
TIMEOUTSHORT = (SAMPLETIME*20)
TIMEOUTLONG = (SAMPLETIME*600)
SENDURLTIME = 0.08
# 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 999
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
#--------------------------------------------------------------
# Gestione coda (condivisa) x registrazione eventi ed invio URL
#print "Creazione coda 1000 elementi"
Coda = Queue.Queue(0)
#queueLock = threading.Lock()
#---------------------------------------------------------------
# lettura parallela
# ritorna il byte letto pulito ( due char hex )
def readParallela():
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 = ''
# print "input : "
# ritorna '' se non ci sono abbastanza caratteri
try:
num_value = 255
# print "num_value : " , num_value , in_0
if GPIO.input(in_0):
num_value = num_value - 1
if GPIO.input(in_1):
num_value = num_value - 2
if GPIO.input(in_2):
num_value = num_value - 4
if GPIO.input(in_3):
num_value = num_value - 8
if GPIO.input(in_4):
num_value = num_value - 16
if GPIO.input(in_5):
num_value = num_value - 32
if GPIO.input(in_6):
num_value = num_value - 64
if GPIO.input(in_7):
num_value = num_value - 128
current = hex( num_value ).replace ( "0x" , "" ).upper()
# print "\n\n\n\n\n" , num_value , current
except:
pass
return current
#--------------------------------------------------------------
# MARCO: cambiare: chiama URL NON deve chiamare url MA METTERE IN CODA (riempiCoda!!!)
# la parte URL vera va messa in svuotaCoda, PARAMETRICA
#---------------------------------------------------------------
#Funzione di scrittura su coda con try-except
def accoda():
try:
# url = URLBASE + idxMacchina + URLADV1 + value
# urllib.urlopen ( url )
#dtEve = time.strftime("%y%m%d%H%M%S")+"000"
dtEve = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')[:-3]
#logPro.debug( "Nuovo valore inserito in coda: " + dtEve + "#" + value + '#' + cont)
#print(dtEve)
#queueLock.acquire()
Coda.put(dtEve + '#' + value + '#' + cont)
#queueLock.release()
#print "Nuovo valore inserito in coda: " + dtEve + "#", value
except Queue.Full:
logPro.error( "Quque full" + dtEve + '#' + value + '#' + cont )
except:
logPro.error( "NETWORK:Errore http-no com rete-timeout" + url )
# print "Url aforte" , url
#--------------------------------------------------------------
# MARCO: scrivere svuotaCoda come thread etc...
def svuota_coda():
global onLine
global sending
global timer_busy
#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'
# formatto dataOra corrente
#dtCurr = time.strftime("%y%m%d%H%M%S")+"000"
dtCurr = datetime.utcnow().strftime('%Y%m%d%H%M%S%f')[:-3]
# prendo 1 valore dalla coda...
#queueLock.acquire()
resp = Coda.get()
# RILASCIO SUBITO la coda x nuovi insert...
#queueLock.release()
# recupero valori da 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)
#logPro.debug(url)
# log valore inviato!
logSnd.info( value + ' ['+ cnt +']' + ' R:' + answ3 )
#print "Valore smaltito dalla coda"
# 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 % 1000 # round robin 1000 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' )
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' )
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 = readParallela()
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