Files
AnaLogger/sampler/FTSampler.py
T
2021-06-04 16:09:37 +02:00

249 lines
9.3 KiB
Python

#!/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():
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))
redSrv0.set('RTDATA:VALUE',round(newValue,3))
# 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()