#!/usr/bin/python import os import math import time import datetime import ADS1256 import redis import FTL.FTLog FTL.FTLog.Write(" FTSampler started") #configurazione per lavorare su server redis locale REDIS_PORT = 6379 REDIS_HOST = '127.0.0.1' redSrv0 = redis.Redis( host=REDIS_HOST, port=REDIS_PORT, db=0) #funzione per leggere e decodificare da redis def getRedisVal(redisKey): if redSrv0.get(redisKey) is None: return redSrv0.get(redisKey) else: return redSrv0.get(redisKey).decode('utf-8') def echoList(redisKey, numVal): currList = redSrv0.lrange(redisKey, 0, numVal) currString = '' for curVal in range(0,numVal,+1): currString = currString + ' ' + str(curVal) + ': ' + str((float)(currList[curVal].decode('utf-8'))) + ' | ' print(currString) def putRedisListVal(redisKey, value, maxLen): #echoList(redisKey, maxLen) redSrv0.lpush(redisKey, value) # se supero lunghezza --> rimuovo redSrv0.ltrim(redisKey, 0, maxLen) #echoList(redisKey, maxLen) def getRmsVal(redisKey, numVal): # leggo lista da redis currList = redSrv0.lrange(redisKey, 0, numVal) numVal= len(currList) # print (len(currList)) sumSquare=0 # per ogni elemento calcolo quadrato for curVal in range(0,numVal,+1): sumSquare = sumSquare + (float)(currList[curVal].decode('utf-8'))*(float)(currList[curVal].decode('utf-8')) # divido e faccio radice quadrata rmsVal = math.sqrt(sumSquare / numVal) return rmsVal #intervallo in millisecondi fra un campionamento e il successivo redSampleFreq = 'SETTINGS:LOG:FREQ' redSrv0.set(redSampleFreq,100) #definizioni variabili redRmsList ='RTDATA:RMSLIST' redSamPer='SETTINGS:LOG:EXETIME' #se non c'è un valore nei campi di redis, popolo il db redSrv0.set('SETTINGS:LOG:STATUS',0) redSrv0.set('SETTINGS:POWER:OFF',0) if redSrv0.get('SETTINGS:DECIMALS:COUNT') is None: redSrv0.set('SETTINGS:DECIMALS:COUNT',1) if redSrv0.get('RTDATA:VALUE:KCONST') is None: redSrv0.set('RTDATA:VALUE:KCONST', 1) if redSrv0.get('SETTINGS:POWER:UPTIME') is None: redSrv0.set('SETTINGS:POWER:UPTIME', 300) if redSrv0.get('SETTINGS:POWER:CH') is None: redSrv0.set('SETTINGS:POWER:CH', 10) if redSrv0.get('RTDATA:VALUE:UMEASURE') is None: redSrv0.set('RTDATA:VALUE:UMEASURE', "-") if redSrv0.get('SETTINGS:LOG:EXETIME') is None: redSrv0.set('SETTINGS:LOG:EXETIME', 1) if redSrv0.get('RTDATA:VALUE') is None: redSrv0.set('RTDATA:VALUE', 1) if redSrv0.get('SETTINGS:POWER:THRESH') is None: redSrv0.set('SETTINGS:POWER:THRESH', 0) if redSrv0.get('SETTINGS:SMOOTHING:FUNCTION') is None: redSrv0.set('SETTINGS:SMOOTHING:FUNCTION', 0) if redSrv0.get('SETTINGS:SMOOTHING:FACTOR') is None: redSrv0.set('SETTINGS:SMOOTHING:FACTOR', 10) if redSrv0.get('SETTINGS:PASSWORD:CURRENT') is None: redSrv0.set('SETTINGS:PASSWORD:CURRENT',"-") if redSrv0.get('SETTINGS:FOLDER:CURRENT') is None: redSrv0.set('SETTINGS:FOLDER:CURRENT', "") if redSrv0.get('SETTINGS:SELECTED_CH') is None: redSrv0.set('SETTINGS:SELECTED_CH',0) if redSrv0.get('SETTINGS:CHANNEL:A') is None: redSrv0.set('SETTINGS:CHANNEL:A',0) if redSrv0.get('SETTINGS:CHANNEL:B') is None: redSrv0.set('SETTINGS:CHANNEL:B',1) if redSrv0.get('RTDATA:SESSION:NAME') is None: redSrv0.set('RTDATA:SESSION:NAME',"") for numCh in range(0,8,+1): if redSrv0.get('SETTINGS:IN:MAX:'+str(numCh)) is None: redSrv0.set('SETTINGS:IN:MAX:'+str(numCh),100) if redSrv0.get('SETTINGS:IN:MIN:'+str(numCh)) is None: redSrv0.set('SETTINGS:IN:MIN:'+str(numCh),0) if redSrv0.get('SETTINGS:OUT:MAX:'+str(numCh)) is None: redSrv0.set('SETTINGS:OUT:MAX:'+str(numCh),100) if redSrv0.get('SETTINGS:OUT:MIN:'+str(numCh)) is None: redSrv0.set('SETTINGS:OUT:MIN:'+str(numCh),0) if redSrv0.get('SETTINGS:UNIT:MEASURE:'+str(numCh)) is None: redSrv0.set('SETTINGS:UNIT:MEASURE:'+str(numCh),"-") if redSrv0.get('RTDATA:CH:'+str(numCh)) is None: redSrv0.set('RTDATA:CH:'+str(numCh),1) if redSrv0.get('RTDATA:OUT:'+str(numCh)) is None: redSrv0.set('RTDATA:OUT:'+str(numCh),1) #funzione salva time+data di log e otto valori su redis def redisSave(CHvalue): decimalsCount = int(getRedisVal('SETTINGS:DECIMALS:COUNT')) smoothFunction= int(getRedisVal('SETTINGS:SMOOTHING:FUNCTION')) smoothFact= int(getRedisVal('SETTINGS:SMOOTHING:FACTOR')) redLastLog = 'RTDATA:TIME:LOG' dateFormat ="%d/%m/%Y %H:%M:%S" rawLastLog = datetime.datetime.now() lastLog = rawLastLog.strftime(dateFormat) redSrv0.set(redLastLog,str(lastLog)) for chIndex in range(0,8,+1): redAreaIn = 'RTDATA:CH:'+str(chIndex) redAreaOut = 'RTDATA:OUT:'+str(chIndex) redRmsArea = redRmsList+':'+str(chIndex) innovazione = float("%.4f" % (CHvalue[chIndex]*5.0/0x7fffff)) strValIn = innovazione # verifico il TIPO di Smoothing richiesto: 0 none, 1 EWMA, 2 RMS if (smoothFunction == 1): # EWMA: RILEGGO DA REDIS vecchio valore oldVal = float(redSrv0.get(redAreaIn)) # effettuo smoothing valore strValIn = (innovazione/smoothFact) + (oldVal * (smoothFact-1) / smoothFact) elif (smoothFunction == 2): # accodo innovazioni putRedisListVal(redRmsArea, innovazione, smoothFact) # calcolo valore RMS strValIn = getRmsVal(redRmsArea, smoothFact) else: # nessuno smooting strValIn = innovazione #salvo valore IN filtrato redSrv0.set(redAreaIn,round(strValIn,8)) # salvo i valori scalati in OUT roundedOut = round(scaleVal(CHvalue[chIndex]*5.0/0x7fffff, chIndex), decimalsCount) redSrv0.set(redAreaOut,roundedOut) #funzione di refresh valori scalati def scaleVal(inValue, chIndex): #rileggo da redis i valori min/max secondo chIndex chInMin = float(0) if (redSrv0.get('SETTINGS:IN:MIN:'+str(chIndex)) != 0): chInMin = float(redSrv0.get('SETTINGS:IN:MIN:'+str(chIndex))) chInMax = float(3.3) if (redSrv0.get('SETTINGS:IN:MAX:'+str(chIndex)) != 100): chInMax = float(redSrv0.get('SETTINGS:IN:MAX:'+str(chIndex))) chOutMin = float(0) if (redSrv0.get('SETTINGS:OUT:MIN:'+str(chIndex)) != 0): chOutMin = float(redSrv0.get('SETTINGS:OUT:MIN:'+str(chIndex))) chOutMax = float(1000) if (redSrv0.get('SETTINGS:OUT:MAX:'+str(chIndex)) != 100): chOutMax = float(redSrv0.get('SETTINGS:OUT:MAX:'+str(chIndex))) # check denom zero deltaOut = (chOutMax - chOutMin) deltaIn = (chInMax - chInMin) if(deltaIn==0): deltaIn = 1 # calcolo scalato outVal = chOutMin + ((inValue-chInMin) * (deltaOut / deltaIn)) return outVal def checkPowerOff(): powerChannel = getRedisVal('SETTINGS:POWER:CH') if(int(powerChannel) < 10): #controllo che non ci sia già una richiesta di spegnimento if(getRedisVal('SETTINGS:POWER:OFF')=="0"): limitVal = float(getRedisVal('SETTINGS:POWER:THRESH')) actVal = float(getRedisVal('RTDATA:CH:' + str(powerChannel))) #controllo che il valore letto sia inferiore al valore impostato di soglia if(actVal < limitVal): #controllo che il sistema sia acceso da 180 secondi prima di spegnere UptimePower = getRedisVal('SETTINGS:POWER:UPTIME') sysUptime = os.popen("awk '{print $1}' /proc/uptime").readline() if float(sysUptime) > float(UptimePower): # chiedo spegnimento redSrv0.set('SETTINGS:POWER:OFF',1) def calculateValue(): decimalsCount = int(getRedisVal('SETTINGS:DECIMALS:COUNT')) ch1 = getRedisVal('SETTINGS:CHANNEL:A') ch2 = getRedisVal('SETTINGS:CHANNEL:B') v1 = getRedisVal('RTDATA:OUT:' + ch1) v2 = getRedisVal('RTDATA:OUT:' + ch2) k = getRedisVal('RTDATA:VALUE:KCONST') den = (float(v1)-float(v2)) if(den < 0.001): den = 0.001 newValue = float(k)*(float(v2)/float(den)) strValIn = newValue # EWMA: RILEGGO DA REDIS vecchio valore oldVal = float(redSrv0.get('RTDATA:VALUE')) if(oldVal == 0): oldVal = 0.01 # se variazione < 50% smooth if((abs(newValue - oldVal) / oldVal) < 0.5): # effettuo smoothing valore eFact = 4 strValIn = (newValue/eFact) + (oldVal * (eFact-1) / eFact) redSrv0.set('RTDATA:VALUE',round(strValIn,decimalsCount)) # init oggetto lettura da try: CH = ADS1256.ADS1256() CH.ADS1256_init() #ciclo principale while(1): redisTime = 'RTDATA:TIME:SRV' now = datetime.datetime.now() dateFormat ="%d/%m/%Y %H:%M:%S" lastLog = now.strftime(dateFormat) redSrv0.set(redisTime,str(lastLog)) CHvalue = CH.ADS1256_GetAll() # salvo valori redisSave(CHvalue) # controllo soglia spegnimento checkPowerOff() #calcolo il valore [V2/(V1-V2)] calculateValue() # riporto ultima esecuzione ad adesso endExec = datetime.datetime.now() # calcolo il delta time dovuto alle esecuzioni delta = endExec - now redSrv0.set('SETTINGS:EXE:TIME',str(delta)) oldSPeriod=float(getRedisVal(redSamPer)) newSPeriod=0.5*oldSPeriod+0.5*(float(delta.microseconds/1000)) redSrv0.set(redSamPer,newSPeriod) waitTime = int(getRedisVal(redSampleFreq)) / 1000 - delta.microseconds/1000000 if(waitTime < 0.01): waitTime = 0.01 # attesa time.sleep(waitTime) #eccezione da ctrl+c in terminale e chiusura except KeyboardInterrupt: FTL.FTLog.Write(" FTSampler stopped by Ctrl+C") exit() #eccezione da errore e chiusura except Exception as errorMessage: FTL.FTLog.Write(str(errorMessage)) exit()