Files
marco.locatelli@steamware.net 90306ac9bf Update pag settings
2023-07-11 14:39:40 +02:00

551 lines
19 KiB
Python

#!/usr/bin/python
from flask import Flask, render_template, jsonify, request
import time
from datetime import datetime
from flask.wrappers import Request
import redis
import os, glob
import json
from werkzeug.utils import redirect
import os.path, time
from distutils.dir_util import copy_tree
import shutil
from gpiozero import LED
import FTL.FTLog
import logging
FTL.FTLog.Write(" FTServer started")
#silenzio i logger
logging.getLogger('werkzeug').disabled = True
os.environ['WERKZEUG_RUN_MAIN'] = 'true'
#definisco il led
led = LED(26)
#assegno ipv4 statico
ipv4 = '10.10.10.210'
#ipv4 = '10.74.82.210'
#definisco directory /data
dataDir='/home/pi/data/'
#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')
flaskApp = Flask(__name__)
flaskApp.config['JSON_SORT_KEYS'] = False
@flaskApp.route("/")
#funzione main: passa al template home il titolo
def main():
channelsData = {
'title' : 'Home'
}
#assegno il template html di riferimento
return render_template('home.html', **channelsData)
@flaskApp.route("/logger")
#funzione logger, route a pagina /logger
def logger():
channelsData = {
'title' : 'Logger'
}
#assegno il template html di riferimento
return render_template('logger.html', **channelsData)
@flaskApp.route("/settings")
#funzione setup, route a pagina /setup
def setup():
channelsData = {
'title' : 'Settings',
}
#assegno il template html di riferimento
return render_template('settings.html', **channelsData)
@flaskApp.route("/about")
#funzione about, route a pagina /about
def about():
channelsData = {
'title' : 'About'
}
#assegno il template html di riferimento
return render_template('about.html', **channelsData)
# funzione api_channels_all: legge direttamente da redis, ritorna jsonify
@flaskApp.route("/api/v1/channels/all", methods=['GET'])
def api_channels_all():
numCh = getRedisVal('SETTINGS:SELECTED_CH')
# check exe time vs sample time
exeWarning = getRedisVal('SETTINGS:WARNING:EXETIME')
displayWarning = 0
if exeWarning == "1":
displayWarning = 1
elif exeWarning == "0":
displayWarning = 0
#check demon warning
denZero = getRedisVal('RTDATA:WARNING:DENOMZERO')
displayDenomWarning = 0
if denZero == "1":
displayDenomWarning = 1
elif denZero == "0":
displayDenomWarning = 0
CH = [0,0,0,0,0,0,0,0]
OUT = [0,0,0,0,0,0,0,0]
OUTMIN = [0,0,0,0,0,0,0,0]
OUTMAX = [0,0,0,0,0,0,0,0]
UNIMISURA = [0,0,0,0,0,0,0,0]
for numCh in range(0,8,+1):
CH[numCh] = getRedisVal('RTDATA:CH:'+str(numCh))
OUT[numCh] = getRedisVal('RTDATA:OUT:'+str(numCh))
OUTMIN[numCh] = getRedisVal('SETTINGS:OUT:MIN:'+str(numCh))
OUTMAX[numCh] = getRedisVal('SETTINGS:OUT:MAX:'+str(numCh))
UNIMISURA[numCh] = getRedisVal('SETTINGS:UNIT:MEASURE:'+str(numCh))
channelsData = {
'timeSrv' : getRedisVal('RTDATA:TIME:SRV'),
'WriteFreq' : getRedisVal('SETTINGS:WRITE:FREQ'),
'DecimalsCount' : getRedisVal('SETTINGS:DECIMALS:COUNT'),
'DecimalsDisplay' : getRedisVal('SETTINGS:DECIMALS:DISPLAY'),
'Status' : getRedisVal('SETTINGS:LOG:STATUS'),
'Channels': CH,
'Outs': OUT,
'Outmin': OUTMIN,
'Outmax': OUTMAX,
'UniMeasure' : UNIMISURA,
'CalcUMeasure' : getRedisVal('RTDATA:VALUE:UMEASURE'),
'ChA' : getRedisVal('SETTINGS:CHANNEL:A'),
'ChB' : getRedisVal('SETTINGS:CHANNEL:B'),
'ChScaleMax' : getRedisVal('SETTINGS:IN:MAX:'+str(numCh)),
'ChScaleMin' : getRedisVal('SETTINGS:IN:MIN:'+str(numCh)),
'ChRealMax' : getRedisVal('SETTINGS:OUT:MAX:'+str(numCh)),
'ChRealMin' : getRedisVal('SETTINGS:OUT:MIN:'+str(numCh)),
'LastSessionName' : getRedisVal('RTDATA:SESSION:NAME'),
'GateOpen': getRedisVal('RTDATA:GATE_OPEN'),
'CurrentWorkFolder' : getRedisVal('SETTINGS:FOLDER:CURRENT'),
'RealDateStatus' : getRedisVal('SETTINGS:TIME:REAL'),
'SelPowerChannel' : getRedisVal('SETTINGS:POWER:CH'),
'SmoothFact' : getRedisVal('SETTINGS:SMOOTHING:FACTOR'),
'EFact' : getRedisVal('SETTINGS:SMOOTHING:EFACT'),
'LogFreq' : getRedisVal('SETTINGS:LOG:FREQ'),
'SelProcessing' : getRedisVal('SETTINGS:SMOOTHING:FUNCTION'),
'ResultValue' : getRedisVal('RTDATA:VALUE:SMOOTHED'),
'RealValue' : getRedisVal('RTDATA:VALUE:SMRAW'),
'Crono' : getRedisVal('SETTINGS:LOG:CRONO'),
'DisplayAlert' : displayWarning,
'DisplayDenomAlert' : displayDenomWarning,
'EwmaEnab' : (redSrv0.get('RTDATA:EWMA:VETO') is None)
}
# restituisce in formato json i dati letti da redis
return jsonify(channelsData)
# definisco una NUOVA route a cui rispondere su chiamta in metodo GET x restituire dati aggiornati
@flaskApp.route("/api/v1/channels/current", methods=['GET'])
def api_channels_current():
numCh = getRedisVal('SETTINGS:SELECTED_CH')
savedPwd = getRedisVal('SETTINGS:PASSWORD:CURRENT')
if savedPwd is None:
redSrv0.set('SETTINGS:PASSWORD:CURRENT',"")
# on load tutto false
showDiv1 = 0
showDiv2 = 0
showDiv3 = 0
if savedPwd == "":
showDiv1 = 1
elif savedPwd == "viaZavaritt":
showDiv3 = 1
elif savedPwd == "viaZavaritt152":
showDiv2 = 1
showDiv3 = 1
#funzione legge direttamente da redis, ritorna jsonify
result = {
'numCh' : numCh,
'CostanteK1' : getRedisVal('RTDATA:VALUE:K1CONST'),
'CostanteK2' : getRedisVal('RTDATA:VALUE:K2CONST'),
'Offset' : getRedisVal('RTDATA:VALUE:OFFSET'),
'CalcUMeasure' : getRedisVal('RTDATA:VALUE:UMEASURE'),
'SmoothFact' : getRedisVal('SETTINGS:SMOOTHING:FACTOR'),
'EFact' : getRedisVal('SETTINGS:SMOOTHING:EFACT'),
'ChanThresh' : getRedisVal('SETTINGS:POWER:THRESH'),
'timeSrv' : getRedisVal('RTDATA:TIME:SRV'),
'LogFreq' : getRedisVal('SETTINGS:LOG:FREQ'),
'DecimalsCount' : getRedisVal('SETTINGS:DECIMALS:COUNT'),
'DecimalsDisplay' : getRedisVal('SETTINGS:DECIMALS:DISPLAY'),
'WriteFreq' : getRedisVal('SETTINGS:WRITE:FREQ'),
'TimeBeforeWrite' : getRedisVal('SETTINGS:LOG:WAITIME'),
'CurrIn' : getRedisVal('RTDATA:CH:'+str(numCh)),
'CurrOut' : getRedisVal('RTDATA:OUT:'+str(numCh)),
'MaxOut' : getRedisVal('SETTINGS:OUT:MAX:'+str(numCh)),
'MinOut' : getRedisVal('SETTINGS:OUT:MIN:'+str(numCh)),
'MaxIn' : getRedisVal('SETTINGS:IN:MAX:'+str(numCh)),
'MinIn' : getRedisVal('SETTINGS:IN:MIN:'+str(numCh)),
'UniMisura' : getRedisVal('SETTINGS:UNIT:MEASURE:'+str(numCh)),
'CurrentWorkFolder' : getRedisVal('SETTINGS:FOLDER:CURRENT'),
'MinUptime' : getRedisVal('SETTINGS:POWER:UPTIME'),
'ShowDiv01' : showDiv1,
'ShowDiv02' : showDiv2,
'ShowDiv03' : showDiv3,
}
# restituisce in formato json i dati letti da redis
return jsonify(result)
# elenco file nella directory
@flaskApp.route("/api/v1/folders/list", methods=['GET'])
def api_get_folders():
folderList = os.listdir(dataDir)
lista = []
idx=0
# for item in sorted(data):
for item in folderList:
current = {"Elenco Cartelle": item}
lista.append(current)
idx=idx+1
return jsonify(folderTable = lista)
# elenco file nella directory
@flaskApp.route("/api/v1/files/list", methods=['GET'])
def api_get_files():
currentFolder = getRedisVal('SETTINGS:FOLDER:CURRENT')
workingDirectory = (dataDir+currentFolder)
if workingDirectory == dataDir:
return "OK"
else:
fileList = os.listdir(workingDirectory)
lista = []
idx=0
# for item in sorted(data):
for item in fileList:
t_obj = time.strptime(time.ctime(os.path.getctime(workingDirectory+"/"+item)))
# Transforming the time object to a timestamp
T_stamp = time.strftime("%Y-%m-%d %H:%M:%S", t_obj)
current = {"Nome": item, "Size (bytes)": os.path.getsize(workingDirectory+"/"+item), "Data creazione":T_stamp}
lista.append(current)
idx=idx+1
return jsonify(fileTable = lista)
# Route di comando x LOG: start e stop
@flaskApp.route("/api/v1/log/start", methods=['PUT'])
#funzione start_log: scrive su redis LOG:STATUS -> 1
def start_log():
currentFolder = getRedisVal('SETTINGS:FOLDER:CURRENT')
workingDirectory = (dataDir+currentFolder)
if workingDirectory != dataDir:
redSrv0.set('SETTINGS:LOG:STATUS', 1)
redSrv0.set('RTDATA:EWMA:VETO', 1)
redSrv0.expire('RTDATA:EWMA:VETO', 2)
#data e time ora
lastDate = datetime.now()
#formato per data time nomefile: YYYYddmm_HMS
format = "%Y%m%d_%H%M%S"
#format date e time adando strftime()
nameDate = lastDate.strftime(format) + ".txt"
redSrv0.set('RTDATA:SESSION:NAME', nameDate)
led.on()
return "OK"
else:
redSrv0.set('SETTINGS:FOLDER:CURRENT', "Default")
currentFolder = getRedisVal('SETTINGS:FOLDER:CURRENT')
workingDirectory = (dataDir+currentFolder)
os.mkdir(workingDirectory)
redSrv0.set('SETTINGS:LOG:STATUS', 1)
redSrv0.set('RTDATA:EWMA:VETO', 1)
redSrv0.expire('RTDATA:EWMA:VETO', 2)
#data e time ora
lastDate = datetime.now()
#formato per data time nomefile: YYYYddmm_HMS
format = "%Y%m%d_%H%M%S"
#format date e time adando strftime()
nameDate = lastDate.strftime(format) + ".txt"
redSrv0.set('RTDATA:SESSION:NAME', nameDate)
led.on()
return "OK"
@flaskApp.route("/api/v1/log/stop", methods=['PUT'])
def stop_log():
#funzione stop_log: scrive su redis LOG:STATUS -> 0
redSrv0.set('SETTINGS:LOG:STATUS', 0)
redSrv0.set('SETTINGS:LOG:WAITER', 0)
redSrv0.set('RTDATA:SESSION:NAME', "")
led.off()
return "OK"
@flaskApp.route("/api/v1/data/navigate", methods=['PUT'])
def data_navigate():
#funzione torna in /data
if(getRedisVal('SETTINGS:LOG:STATUS') == "0"):
redSrv0.set('SETTINGS:FOLDER:CURRENT',"")
return redirect("/logger")
else:
return redirect("/logger")
@flaskApp.route("/api/v1/data/export", methods=['PUT'])
def data_export():
#funzione dataExport: copia
currentFolder = getRedisVal('SETTINGS:FOLDER:CURRENT')
workingDirectory = (dataDir+currentFolder)
scriptMount = """
if [ -a /dev/sd[a-z]1 ]
then
/bin/mount /dev/sd[a-z]1 /mnt/USB
else
/bin/mount /dev/sd[a-z] /mnt/USB
fi
"""
scriptUnmount = """
sync
/bin/umount /mnt/USB
"""
os.system("bash -c '%s'" % scriptMount)
usbDrive='/mnt/USB/'
dataDestination = (usbDrive+currentFolder)
if os.path.isdir(dataDestination) is True:
copy_tree(workingDirectory, dataDestination)
else:
os.mkdir(dataDestination)
copy_tree(workingDirectory, dataDestination)
os.system("bash -c '%s'" % scriptUnmount)
return redirect("/logger")
@flaskApp.route("/api/v1/data/delete", methods=['PUT'])
def data_delete():
#funzione dataDelete: cancella
currentFolder = getRedisVal('SETTINGS:FOLDER:CURRENT')
workingDirectory = (dataDir+currentFolder)
if dataDir == workingDirectory:
return redirect("/logger")
else:
if(getRedisVal('SETTINGS:LOG:STATUS') == "0"):
shutil.rmtree(workingDirectory)
redSrv0.set('SETTINGS:FOLDER:CURRENT', "")
return redirect("/logger")
else:
return redirect("/logger")
@flaskApp.route("/api/v1/setup/dateTime", methods=['POST'])
def insertDateTime():
#funzione inserimento data e ora
newDateTime = request.form['dateTimeInput']
if newDateTime == "":
return redirect("/settings")
else:
workedDateTime = datetime.strptime(newDateTime, '%Y-%m-%dT%H:%M')
#formato per salvare data YYYYmmdd
formatDate = "%Y%m%d"
newDate = workedDateTime.strftime(formatDate)
#formato per salvare time hh.mm
formatTime = "%H:%M"
newTime = workedDateTime.strftime(formatTime)
#imposto data e time su raspberry:
os.system("sudo date +%Y%m%d -s " + str(newDate))
os.system("sudo date +%T -s " + str(newTime))
redSrv0.set('SETTINGS:TIME:REAL',1)
return redirect("/logger")
@flaskApp.route("/api/v1/setup/passwordInput", methods=['POST'])
def insertPassword():
#funzione inserimento password
currentPassword = request.form['PasswordForm']
redSrv0.set('SETTINGS:PASSWORD:CURRENT', currentPassword, ex=3600)
return redirect("/settings")
@flaskApp.route("/api/v1/setup/setupValues", methods=['PUT'])
def setupValues():
redSrv0.set('SETTINGS:SMOOTHING:FACTOR', 100)
redSrv0.set('SETTINGS:LOG:FREQ', 10)
redSrv0.save()
return redirect("/settings")
@flaskApp.route("/api/v1/setup/workingValues", methods=['PUT'])
def workingValues():
redSrv0.set('SETTINGS:SMOOTHING:FACTOR', 25)
redSrv0.set('SETTINGS:LOG:FREQ', 20)
redSrv0.save()
return redirect("/settings")
@flaskApp.route("/api/v1/setup/saveInMin", methods=['PUT'])
def setupInMin():
# devo leggere il channel attualmente selezionato
indCh = getRedisVal('SETTINGS:SELECTED_CH')
currChVal = redSrv0.get('RTDATA:CH:'+ str(indCh))
redSrv0.set('SETTINGS:IN:MIN:'+ str(indCh), currChVal)
redSrv0.save()
return redirect("/settings")
@flaskApp.route("/api/v1/setup/saveInMax", methods=['PUT'])
def setupInMax():
# devo leggere il channel attualmente selezionato
indCh = getRedisVal('SETTINGS:SELECTED_CH')
currChVal = redSrv0.get('RTDATA:CH:'+ str(indCh))
redSrv0.set('SETTINGS:IN:MAX:'+ str(indCh), currChVal)
redSrv0.save()
return redirect("/settings")
@flaskApp.route("/api/v1/setup/selectChannelA/<numChA>", methods=['PUT'])
def selectChannelA(numChA):
redSrv0.set('SETTINGS:CHANNEL:A', numChA)
redSrv0.save()
return "OK"
@flaskApp.route("/api/v1/setup/selectChannelB/<numChB>", methods=['PUT'])
def selectChannelB(numChB):
redSrv0.set('SETTINGS:CHANNEL:B', numChB)
redSrv0.save()
return "OK"
@flaskApp.route("/api/v1/setup/selectChannel/<numCh>", methods=['PUT'])
def setChannel(numCh):
redSrv0.set('SETTINGS:SELECTED_CH', numCh)
redSrv0.save()
return redirect("/settings")
@flaskApp.route("/api/v1/setup/selectPowerChannel/<numPowerCh>", methods=['PUT'])
def setPowerChannel(numPowerCh):
redSrv0.set('SETTINGS:POWER:CH', numPowerCh)
redSrv0.save()
return "OK"
@flaskApp.route("/api/v1/setup/calcMeasureUnit", methods=['POST'])
def VUnitMeasure():
CMeasureUnit = request.form['CalcUMeasure']
redSrv0.set('RTDATA:VALUE:UMEASURE', CMeasureUnit)
redSrv0.save()
return redirect("/settings")
@flaskApp.route("/api/v1/setup/selectProcessing/<processingType>", methods=['PUT'])
def setProcessing(processingType):
redSrv0.set('SETTINGS:SMOOTHING:FUNCTION', processingType)
redSrv0.save()
return "OK"
@flaskApp.route("/api/v1/threshold", methods=['POST'])
def setPowerThreshold():
powerThreshold = request.form['ChanThresh']
redSrv0.set('SETTINGS:POWER:THRESH', powerThreshold)
minUptime = request.form['MinUptime']
redSrv0.set('SETTINGS:POWER:UPTIME', minUptime)
redSrv0.save()
# rimando in settings
return redirect("/settings")
@flaskApp.route("/api/v1/smoothFact", methods=['POST'])
def setSmoothFact():
smoothingFactor = request.form['SmoothFact']
redSrv0.set('SETTINGS:SMOOTHING:FACTOR', smoothingFactor)
redSrv0.save()
# rimando in settings
return redirect("/settings")
@flaskApp.route("/api/v1/eFact", methods=['POST'])
def setEFact():
eFactor = request.form['EFact']
redSrv0.set('SETTINGS:SMOOTHING:EFACT', eFactor)
redSrv0.save()
# rimando in settings
return redirect("/settings")
@flaskApp.route("/api/v1/frequency", methods=['POST'])
def setWriteFrequency():
#funzione set frequenza scrive su redis LOG:FREQ prendendolo dall'input in pagina html con nome LogFreq
newLogFrequency = request.form['LogFreq']
redSrv0.set('SETTINGS:LOG:FREQ', newLogFrequency)
newWriteFrequency = request.form['WriteFreq']
redSrv0.set('SETTINGS:WRITE:FREQ', newWriteFrequency)
timeBeforeWrite = request.form['TimeBeforeWrite']
redSrv0.set('SETTINGS:LOG:WAITIME', timeBeforeWrite)
redSrv0.save()
# rimando in settings
return redirect("/settings")
@flaskApp.route("/api/v1/decimalsCount", methods=['POST'])
def setDecimalsCount():
#funzione set decimali per i calcoli, scrive su SETTINGS:DECIMALS:COUNT
newDecimalsCount = request.form['DecimalsCount']
redSrv0.set('SETTINGS:DECIMALS:COUNT', newDecimalsCount)
redSrv0.save()
# rimando in settings
return redirect("/settings")
@flaskApp.route("/api/v1/decimalsDisplay", methods=['POST'])
def setDecimalsDisplay():
#funzione set decimali da mostrare, scrive su SETTINGS:DECIMALS:DISPLAY
newDecimalsDisplay = request.form['DecimalsDisplay']
redSrv0.set('SETTINGS:DECIMALS:DISPLAY', newDecimalsDisplay)
redSrv0.save()
# rimando in settings
return redirect("/settings")
@flaskApp.route("/api/v1/kconst", methods=['POST'])
def setKConst():
#scrive su redis la costante K
newK1Const = request.form['K1Const']
redSrv0.set('RTDATA:VALUE:K1CONST', newK1Const)
newK2Const = request.form['K2Const']
redSrv0.set('RTDATA:VALUE:K2CONST', newK2Const)
newOffset = request.form['Offset']
redSrv0.set('RTDATA:VALUE:OFFSET', newOffset)
redSrv0.save()
# rimando in settings
return redirect("/settings")
@flaskApp.route("/api/v1/setup/workingtree", methods=['POST'])
def setWorkingTree():
#funzione set directory scrive su redis il testo preso dall'input in settings
newWorkFolder = request.form['NewFolder']
redSrv0.set('SETTINGS:FOLDER:CURRENT', newWorkFolder)
currentFolder = getRedisVal('SETTINGS:FOLDER:CURRENT')
workingDirectory = (dataDir+currentFolder)
if os.path.isdir(workingDirectory) is True:
return redirect("/logger")
else:
os.mkdir(workingDirectory)
return redirect("/logger")
@flaskApp.route("/api/v1/scale", methods=['POST'])
def setScale():
indexCh = getRedisVal('SETTINGS:SELECTED_CH')
inputMin = request.form['MinIn']
redSrv0.set('SETTINGS:IN:MIN:'+ str(indexCh), inputMin)
inputMax = request.form['MaxIn']
redSrv0.set('SETTINGS:IN:MAX:'+ str(indexCh), inputMax)
scaleMin = request.form['MinOut']
redSrv0.set('SETTINGS:OUT:MIN:'+ str(indexCh), scaleMin)
scaleMax = request.form['MaxOut']
redSrv0.set('SETTINGS:OUT:MAX:'+ str(indexCh), scaleMax)
uniMisura = request.form['UniMisura']
redSrv0.set('SETTINGS:UNIT:MEASURE:'+ str(indexCh), uniMisura)
redSrv0.save()
# rimando in settings
return redirect("/settings")
@flaskApp.route("/api/v1/setup/resetSettings", methods=['POST'])
def resetSetup():
FTL.FTLog.Write(" FTServer asked redis flushall")
os.system("sudo redis-cli flushall")
return redirect("/logger")
@flaskApp.route("/api/v1/setup/poweroff", methods=['PUT'])
def FTShutdown():
redSrv0.set('SETTINGS:TIME:REAL',0)
FTL.FTLog.Write(" FTServer asked a shutdown")
redSrv0.set('SETTINGS:POWER:OFF',1)
#spegne il sistema
#dichiaro host ipv4 (ottenuto sopra utilizzando il modulo socket)
if __name__ == "__main__":
FTL.FTLog.Write(" FTServer starting Flask Hosting!")
flaskApp.run(host=ipv4, port=80, debug=True)