From eff044934c96d5d3bb7282b33ccdd707cc6969a8 Mon Sep 17 00:00:00 2001 From: Marco Locatelli Date: Fri, 18 Jun 2021 16:44:30 +0200 Subject: [PATCH] 1.3.0, nuova gestione con vettori dei dati --- logger/FTLogger.py | 9 ++ sampler/FTSampler.py | 162 ++++++++++++++++------------------- server/FTServer.py | 6 +- server/templates/about.html | 2 +- server/templates/logger.html | 59 ++++++++----- 5 files changed, 124 insertions(+), 114 deletions(-) diff --git a/logger/FTLogger.py b/logger/FTLogger.py index c90672b..c91758c 100644 --- a/logger/FTLogger.py +++ b/logger/FTLogger.py @@ -39,6 +39,7 @@ redSrv0.set(redWriteFreq,startingWriteFreq) redisTime = 'RTDATA:TIME:SRV' redSrv0.set('SETTINGS:LOG:STATUS',0) redSrv0.set('SETTINGS:POWER:OFF',0) +redSrv0.set('SETTINGS:LOG:CRONO', "00:00:00") if redSrv0.get('SETTINGS:LOG:WAITIME') is None: redSrv0.set('SETTINGS:LOG:WAITIME', 2) if redSrv0.get('SETTINGS:SELECTED_CH') is None: @@ -88,16 +89,24 @@ def fileSave(): outFile.write(csvRow +"\r\n") outFile.close() + #ciclo principale, salva time attuale e se LOG:STATUS è 1 fa fileSave() while(1): now = datetime.datetime.now() # solo se su redis LOG è 1 eseguo il ciclo principale if(getRedisVal('SETTINGS:LOG:STATUS') == "1"): + redSrv0.set('SETTINGS:LOG:CRONO', "00:00:00") #attendo 2 secondi all'avvio della registrazione if(getRedisVal('SETTINGS:LOG:WAITER') == "0"): time.sleep(int(getRedisVal('SETTINGS:LOG:WAITIME'))) + #salvo startTime per inizio cronometro registrazione + startTime = time.perf_counter() + #FTL.FTLog.Write("FTLogger: " + str(start_time)) redSrv0.set('SETTINGS:LOG:WAITER', 1) fileSave() + #a ogni fileSave() misuro tempo trascorso da inizio registrazione e lo mostro + crono = time.strftime('%H:%M:%S', time.gmtime(int(time.perf_counter() - startTime))) + redSrv0.set('SETTINGS:LOG:CRONO',crono) # riporto ultima esecuzione ad adesso endExec = datetime.datetime.now() # calcolo il delta dovuto alle esecuzioni diff --git a/sampler/FTSampler.py b/sampler/FTSampler.py index 83dbe67..4155141 100644 --- a/sampler/FTSampler.py +++ b/sampler/FTSampler.py @@ -1,5 +1,6 @@ #!/usr/bin/python +from array import * import os import math import time @@ -7,6 +8,7 @@ import datetime import ADS1256 import redis import FTL.FTLog +import numpy as np FTL.FTLog.Write(" FTSampler started") @@ -25,45 +27,15 @@ def getRedisVal(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) - 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' +redSampleFreq = 'SETTINGS:LOG:FREQ' #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:LOG:FREQ') is None: + redSrv0.set('SETTINGS:LOG:FREQ', 50) if redSrv0.get('SETTINGS:DECIMALS:COUNT') is None: redSrv0.set('SETTINGS:DECIMALS:COUNT',1) if redSrv0.get('RTDATA:VALUE:K1CONST') is None: @@ -119,11 +91,27 @@ for numCh in range(0,8,+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')) +# calcola la media (colonna x colonna) dei valori ricevuti +def calcMean(dataArray): + outValues = [0.0] * 8 smoothFunction= int(getRedisVal('SETTINGS:SMOOTHING:FUNCTION')) smoothFact= int(getRedisVal('SETTINGS:SMOOTHING:FACTOR')) + # verifico il TIPO di Smoothing richiesto: 0 none, 1 media semplice, 2 RMS + if (smoothFunction == 1): + # effettuo calcolo media mobile + outValues = np.sum(dataArray, axis=0) / smoothFact + elif (smoothFunction == 2): + # calcolo i quadrati + outValues = np.sqrt(np.sum(np.square(dataArray), axis=0) / smoothFact) + else: + # nessuno smooting, passa il primo dei sample acquisiti + outValues = dataArray[0] + # restituisco valori calcolati + return outValues + +#funzione salva time+data di log e otto valori su redis +def redisSave(CHvalues): + decimalsCount = int(getRedisVal('SETTINGS:DECIMALS:COUNT')) redLastLog = 'RTDATA:TIME:LOG' dateFormat ="%d/%m/%Y %H:%M:%S" rawLastLog = datetime.datetime.now() @@ -132,30 +120,11 @@ def redisSave(CHvalue): 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 - + strValIn = float("%.4f" % (CHvalues[chIndex])) #salvo valore IN filtrato - redSrv0.set(redAreaIn,round(strValIn,8)) - + redSrv0.set(redAreaIn,round(strValIn,decimalsCount)) # salvo i valori scalati in OUT - roundedOut = round(scaleVal(CHvalue[chIndex]*5.0/0x7fffff, chIndex), decimalsCount) + roundedOut = round(scaleVal(CHvalues[chIndex], chIndex), decimalsCount) redSrv0.set(redAreaOut,roundedOut) #funzione di refresh valori scalati @@ -207,9 +176,9 @@ def calculateValue(): k1 = getRedisVal('RTDATA:VALUE:K1CONST') k2 = getRedisVal('RTDATA:VALUE:K2CONST') offset = getRedisVal('RTDATA:VALUE:OFFSET') - den = (float(v1)-float(v2)) - if(den < 0.001): - den = 0.001 + den = abs(float(v1)-float(v2)) + if(den < 0.01): + den = 0.01 XVal = (float(v2)/float(den)) newValue = (float(k1)*float(XVal)*float(XVal))+(float(k2)*float(XVal))+float(offset) redSrv0.set('RTDATA:VALUE:REAL',round(newValue,decimalsCount)) @@ -225,38 +194,55 @@ def calculateValue(): strValIn = (newValue/eFact) + (oldVal * (eFact-1) / eFact) redSrv0.set('RTDATA:VALUE:SMOOTHED',round(strValIn,decimalsCount)) -# init oggetto lettura da +# init array +smoothFact= int(getRedisVal('SETTINGS:SMOOTHING:FACTOR')) +initArray = [0.0] * 8 +meanValues = [0.0] * 8 +dataBox = np.array([initArray] * smoothFact) +redisTime = 'RTDATA:TIME:SRV' + +# init oggetto lettura Digital Analog 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 k*[V2/(V1-V2)] + offset - 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) + # update freq campionamento da redis + sampleFreq = getRedisVal(redSampleFreq) + smoothFact= int(getRedisVal('SETTINGS:SMOOTHING:FACTOR')) + dataBox = np.array([initArray] * smoothFact) + for counter in range(0,smoothFact,+1): + now = datetime.datetime.now() + dateFormat ="%d/%m/%Y %H:%M:%S" + lastLog = now.strftime(dateFormat) + redSrv0.set(redisTime,str(lastLog)) + # leggo gli 8 valori + CHvalue = CH.ADS1256_GetAll() + floatArray = np.array(CHvalue, dtype=np.float) + dataBox[counter] = floatArray*float(5.0/0x7fffff) + # calcolo e scrittura ogni NUM PERIOD cicli + if counter == (smoothFact-1): + # faccio gli smoothing colonna x colonna + meanValues = calcMean(dataBox) + #salvo valori + redisSave(meanValues) + # controllo soglia spegnimento + checkPowerOff() + # calcolo il valore k*[V2/(V1-V2)] + offset + calculateValue() + # riporto ultima esecuzione ad adesso + endExec = datetime.datetime.now() + # calcolo il delta time dovuto alle esecuzioni + delta = endExec - now + # attesa viene fatta sempre + waitTime = int(sampleFreq) / 1000 - delta.microseconds/1000000 + if(waitTime < 0.01): + #FTL.FTLog.Write("delta: " + str(delta.microseconds/1000) + " | wait: " + str(waitTime*1000)) + waitTime = 0.01 + #FTL.FTLog.Write("delta: " + str(delta.microseconds/1000) + " | wait: " + str(waitTime*1000)) + # vera attesa + time.sleep(waitTime) #eccezione da ctrl+c in terminale e chiusura except KeyboardInterrupt: diff --git a/server/FTServer.py b/server/FTServer.py index 0e6819b..c9cfd49 100644 --- a/server/FTServer.py +++ b/server/FTServer.py @@ -17,6 +17,7 @@ import logging FTL.FTLog.Write(" FTServer started") +#silenzio i logger logging.getLogger('werkzeug').disabled = True os.environ['WERKZEUG_RUN_MAIN'] = 'true' @@ -123,7 +124,8 @@ def api_channels_all(): 'SelPowerChannel' : getRedisVal('SETTINGS:POWER:CH'), 'SelProcessing' : getRedisVal('SETTINGS:SMOOTHING:FUNCTION'), 'ResultValue' : getRedisVal('RTDATA:VALUE:SMOOTHED'), - 'RealValue' : getRedisVal('RTDATA:VALUE:REAL') + 'RealValue' : getRedisVal('RTDATA:VALUE:REAL'), + 'Crono' : getRedisVal('SETTINGS:LOG:CRONO') } # restituisce in formato json i dati letti da redis return jsonify(channelsData) @@ -497,5 +499,5 @@ def FTShutdown(): #dichiaro host ipv4 (ottenuto sopra utilizzando il modulo socket) if __name__ == "__main__": - FTL.FTLog.Write(" FTServer starting Flask Host!") + FTL.FTLog.Write(" FTServer starting Flask Hosting!") flaskApp.run(host=ipv4, port=80, debug=True) diff --git a/server/templates/about.html b/server/templates/about.html index c35261b..817335b 100644 --- a/server/templates/about.html +++ b/server/templates/about.html @@ -29,7 +29,7 @@
Software di lettura e scrittura per canali analogici e digitali
- V 1.2.1 + V 1.3.0 diff --git a/server/templates/logger.html b/server/templates/logger.html index 6f392c4..c581a46 100644 --- a/server/templates/logger.html +++ b/server/templates/logger.html @@ -44,6 +44,7 @@ $("#CurrentFolder").html(result.CurrentWorkFolder); $("#ResultValue").html(result.ResultValue); $("#RealValue").html(result.RealValue); + $("#Crono").html(result.Crono); if(result.GateOpen == "0") { @@ -304,9 +305,9 @@
-
+
-
+
Canale A:
@@ -314,15 +315,15 @@
- - + +
-
+
Canale B:
@@ -330,41 +331,53 @@
- - + +
-
-
- Risultante = k*[B/(A-B)]+offset -
-
-
-
- Istant: - -
-
- Media: - +
+
+
+
+
+ Risultante B/(A-B) +
+
+
+
+
+
+ Istant: + +
+
+ Media: + +
+
+
+
+
-
-
+
-
+
+ +
+