9e9a63ea1a
Update startBrowser x MON PI
284 lines
11 KiB
Python
284 lines
11 KiB
Python
#!/usr/bin/python
|
|
|
|
from array import *
|
|
import os
|
|
import math
|
|
import time
|
|
import datetime
|
|
import ADS1256
|
|
import redis
|
|
import FTL.FTLog
|
|
import numpy as np
|
|
|
|
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')
|
|
|
|
#definizioni variabili
|
|
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:WARNING:EXETIME') is None:
|
|
redSrv0.set('SETTINGS:WARNING:EXETIME',0)
|
|
if redSrv0.get('SETTINGS:LOG:FREQ') is None:
|
|
redSrv0.set('SETTINGS:LOG:FREQ', 100)
|
|
if redSrv0.get('SETTINGS:DECIMALS:COUNT') is None:
|
|
redSrv0.set('SETTINGS:DECIMALS:COUNT',1)
|
|
if redSrv0.get('RTDATA:VALUE:K1CONST') is None:
|
|
redSrv0.set('RTDATA:VALUE:K1CONST', 0)
|
|
if redSrv0.get('RTDATA:VALUE:K2CONST') is None:
|
|
redSrv0.set('RTDATA:VALUE:K2CONST', 1)
|
|
if redSrv0.get('RTDATA:VALUE:OFFSET') is None:
|
|
redSrv0.set('RTDATA:VALUE:OFFSET', 0)
|
|
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', "kOhm")
|
|
if redSrv0.get('SETTINGS:LOG:EXETIME') is None:
|
|
redSrv0.set('SETTINGS:LOG:EXETIME', 1)
|
|
if redSrv0.get('RTDATA:VALUE:SMOOTHED') is None:
|
|
redSrv0.set('RTDATA:VALUE:SMOOTHED', 1)
|
|
if redSrv0.get('RTDATA:VALUE:RAW') is None:
|
|
redSrv0.set('RTDATA:VALUE:RAW', 1)
|
|
if redSrv0.get('RTDATA:VALUE:REAL') is None:
|
|
redSrv0.set('RTDATA:VALUE:REAL', 1)
|
|
if redSrv0.get('RTDATA:VALUE:SMRAW') is None:
|
|
redSrv0.set('RTDATA:VALUE:SMRAW', 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',2)
|
|
if redSrv0.get('SETTINGS:CHANNEL:B') is None:
|
|
redSrv0.set('SETTINGS:CHANNEL:B',3)
|
|
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),"V")
|
|
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)
|
|
|
|
# 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()
|
|
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)
|
|
strValIn = float("%.4f" % (CHvalues[chIndex]))
|
|
#salvo valore IN filtrato
|
|
redSrv0.set(redAreaIn,round(strValIn,decimalsCount))
|
|
# salvo i valori scalati in OUT
|
|
roundedOut = round(scaleVal(CHvalues[chIndex], 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 abbia superato l'uptime minimo impostato su redis
|
|
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():
|
|
# funzione per calcolare valore risultante (B/A-B)
|
|
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)
|
|
k1 = getRedisVal('RTDATA:VALUE:K1CONST')
|
|
k2 = getRedisVal('RTDATA:VALUE:K2CONST')
|
|
offset = getRedisVal('RTDATA:VALUE:OFFSET')
|
|
den = abs(float(v1)-float(v2))
|
|
if(den < 0.01):
|
|
den = 0.01
|
|
# calcolo il valore risultante pulito (senza correzioni)
|
|
XVal = (float(v2)/float(den))
|
|
redSrv0.set('RTDATA:VALUE:RAW',round(XVal,decimalsCount))
|
|
|
|
# Smoothing EWMA valori "grezzi""
|
|
strValInRaw = XVal
|
|
# EWMAx RAW RILEGGO DA REDIS vecchio valore
|
|
oldValRaw = float(redSrv0.get('RTDATA:VALUE:SMRAW'))
|
|
if(oldValRaw == 0):
|
|
oldValRaw = 0.01
|
|
# se variazione < 50% smooth, altrimenti usa il valore nuovo
|
|
if((abs(XVal - oldValRaw) / oldValRaw) < 0.5):
|
|
# effettuo smoothing valore
|
|
eFact = 3
|
|
strValInRaw = (XVal/eFact) + (oldValRaw * (eFact-1) / eFact)
|
|
redSrv0.set('RTDATA:VALUE:SMRAW',round(strValInRaw,decimalsCount))
|
|
|
|
# applicazione correzioni (costanti k1*x^2, k2*x e offset)
|
|
newValue = (float(k1)*float(XVal)*float(XVal))+(float(k2)*float(XVal))+float(offset)
|
|
redSrv0.set('RTDATA:VALUE:REAL',round(newValue,decimalsCount))
|
|
|
|
# Smoothing EWMA valori corretti (fattori k1 k2)
|
|
strValIn = newValue
|
|
# EWMA: RILEGGO DA REDIS vecchio valore
|
|
oldVal = float(redSrv0.get('RTDATA:VALUE:SMOOTHED'))
|
|
if(oldVal == 0):
|
|
oldVal = 0.01
|
|
# se variazione < 50% smooth, altrimenti usa il valore nuovo
|
|
if((abs(newValue - oldVal) / oldVal) < 0.5):
|
|
# effettuo smoothing valore
|
|
eFact = 3
|
|
strValIn = (newValue/eFact) + (oldVal * (eFact-1) / eFact)
|
|
redSrv0.set('RTDATA:VALUE:SMOOTHED',round(strValIn,decimalsCount))
|
|
|
|
|
|
# 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):
|
|
# update freq campionamento da redis
|
|
sampleFreq = getRedisVal(redSampleFreq)
|
|
smoothFact= int(getRedisVal('SETTINGS:SMOOTHING:FACTOR'))
|
|
dataBox = np.array([initArray] * smoothFact)
|
|
now = datetime.datetime.now()
|
|
dateFormat ="%d/%m/%Y %H:%M:%S"
|
|
lastLog = now.strftime(dateFormat)
|
|
redSrv0.set(redisTime,str(lastLog))
|
|
for counter in range(0,smoothFact,+1):
|
|
# leggo gli 8 valori
|
|
CHvalue = CH.ADS1256_GetAll()
|
|
floatArray = np.array(CHvalue, dtype=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)*smoothFact)/1000 - delta.microseconds/1000000
|
|
if(waitTime < 0.0):
|
|
redSrv0.set('SETTINGS:WARNING:EXETIME',1)
|
|
else:
|
|
redSrv0.set('SETTINGS:WARNING:EXETIME',0)
|
|
if(waitTime < 0.001):
|
|
waitTime = 0.001
|
|
# vera 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(" FTSampler stopped: " + errorMessage))
|
|
exit() |