##
# Copyright (c) 2021 Xilinx, Inc.
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and 
# associated documentation files (the "Software"), to deal in the Software without restriction, including 
# without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
# copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to 
# the following conditions: 
# 
# The above copyright notice and this permission notice shall be included in all copies or substantial 
# portions of the Software. 
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT 
# LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# 
#
##
from flask import Flask, request, redirect, url_for, abort, jsonify, send_from_directory, Response, send_file
from flask_pymongo import PyMongo
#from flask_classy import FlaskView, route
import json, math
import yaml
from bson import json_util
import os,sys,inspect,importlib,string,shutil
from datetime import datetime, timedelta
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
parentdir = os.path.dirname(currentdir)
apidir = os.path.join(parentdir,"api")
sys.path.insert(0,parentdir)
from backend.ysocket import *
from backend.tcpclient import *
from backend import plot
from backend import syswatch
from backend import performanceview
from flask_cors import CORS
from werkzeug.utils import secure_filename
import re,itertools,operator,zipfile
from pathlib import Path
import copy,pymongo
import users
import subprocess
import exception_handler

#-----------------------
import logging
from logging.handlers import RotatingFileHandler
from time import strftime
import traceback
logdir = os.path.join(parentdir,"Session_Log")
logger = logging.getLogger('tdm')
handler = RotatingFileHandler('app.log', maxBytes=100000, backupCount=3)
formatter = logging.Formatter('%(asctime)s : %(levelname)-8s : %(message)s')
handler.setFormatter(formatter)
logger.setLevel(logging.ERROR)
logger.addHandler(handler)
#------------------------
refClock = float(100/3)

UPLOAD_FOLDER = '.'
ALLOWED_EXTENSIONS = set(['tcl', 'xregv','txt'])
# ysocket.connectionstatus = 1
app = Flask(__name__)
app.config.from_pyfile("settings.py")
mongo = PyMongo(app)
CORS(app)


app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['MONGO_URI'] = settings.MONGO_URI

def remove_older_folder(folder="", file="",days=0):
    status = False
    for fpath, ffolder, ffile in os.walk(os.path.join(apidir,"log",folder,file)):
        for i in ffolder:
            try:
                mfoldertime = datetime.datetime.fromtimestamp(os.path.getmtime(os.path.join(fpath,i)))
                # print("folder",mfoldertime)
                # print(i," folder older is ",(datetime.datetime.now() - mfoldertime).days)
                diff_days = (datetime.datetime.now() - mfoldertime).days
                if int(diff_days) >= int(days):
                    ppath = os.path.join(fpath,i)
                    if os.path.isdir(ppath):
                        shutil.rmtree(ppath)
                        status = True
                    else:
                        os.remove(ppath)
                        status = True
            except Exception as e:
                return {"error":str(e)}
    if not status:
        return {"error":"file not found"}
    return {"msg":"success"}

#reset all active connectionstatus to inactive while restart server
mongo.db.usercollection.update_many({"connectionstatus":1},{"$set":{"connectionstatus":0, "status": "I"}})
#remove 1 week old log file
remove_older_folder(days=15)


c_id=100
module={"module_name" : "","data" : [],"time" : ""}

sub_module={"sub_module_name" : "","data" : []}

monitor={"monitor_name" : "","accumulated_latency" : [],"brust_count" : "","transaction_count":""}

mepll = {"00":"REF_CLK","01":"REF_CLK","10":"NPI_CLK","11":"PL_ALT_REF_CLK"}
mediv={"00":0,"01":2,"10":4,"11":8}
srcselval = {"000":"PPLL","001":"RPLL","010":"APLL","011":"NPLL"}
clkoutdivval = {"00":1,"01":2,"10":4,"11":8}
clkoutdiv = "[17:16]"
fbdiv = "[15:8]"
# targetfreq = {"PPLL":1000,"RPLL":1500,"APLL":1700,"NPLL":1200}
bypassbit = "[3]"
mefreq = {"REF_CLK":60,"NPI_CLK":30,"PL_ALT_REF_CLK":60}

operation_dic = {
    "read": "mrd",
    "write": "mwr"
 }
choice_dic = {
    "by_name" : "instance_name",
    "by_address": "base_address"
}
collection_name = {"PS":"xregv80","NPI":"xregv80_npm", "DDR":"xregv80_npm", "CPM":"xregvcpm", "AI_Engine":"xregvme", "PL":"xregvpl"}
drilldownLabel = ["instance_name", "registers.name", "registers.fields.name"]
threadarr=[]
socketdetails = {}

cpmpll = {"00":"REF_CLK","01":"REF_CLK","10":"REF_CLK","11":"PL_ALT_REF_CLK"}
clock_pll = {"me":"MPLL","cpm":"PLL"}
clock_ref = {"me":{"ME_CORE_REF_CTRL":"0xF70A0138","ME_LSBUS_REF_CTRL":"0XF70A013C","ME_DBG_REF_CTRL":"0XF70A0140"},"cpm":{"CPM_CORE_REF_CTRL":"0xFCA00100","CPM_LSBUS_REF_CTRL":"0XFCA00104","CPM_DBG_REF_CTRL":"0XFCA00108", "CPM_TOPSW_REF_CTRL":"0xFF5E015C"}}
clock_ctrl = {"me":"0xF70A0100","cpm":"0xFCA00040"}



def createisolationobj(isolation_details,uniquekey):
    isolation_temp_address = "0"
    isolation_live_value = ""
    for i in range(len(isolation_details)):
        if isolation_details[i]["absolute_address"] != isolation_temp_address:
            isolation_temp_address = isolation_details[i]["absolute_address"]
            isolation_details[i]["registers_live_value"] = getcommandresponse(
                "mrd %s\n" % isolation_details[i]["absolute_address"], "isolation", socketdetails[uniquekey])
            isolation_details[i]["registers_live_value"] = getcommandresponse(
                "mrd %s\n" % isolation_details[i]["absolute_address"], "isolation", socketdetails[uniquekey])
            isolation_live_value = isolation_details[i]["registers_live_value"]
        else:
            isolation_details[i]["registers_live_value"] = isolation_live_value
        if "error" not in isolation_details[i]["registers_live_value"]:
            tempvalue = bin(int(isolation_details[i]["registers_live_value"], 16))[2:]
            while len(tempvalue) < 32:
                tempvalue = '0' + tempvalue
            isolation_details[i]["fields_value"] = findbitvalue(tempvalue, isolation_details[i]["field_width"])
        else:
            isolation_details[i]["fields_value"] = "--"
    return isolation_details

def createcustomdashboardresponse(obj,response,client,version):
    if "error" in obj:
        response["error"] = obj["error"]
        return response
    if obj["command"] == "mrd" and "write_value" in obj:
        response["error"] = "Invalid format"
        return response

    for j in range(len(obj["matchfilter"])):
        if "address" in obj["matchfilter"][j]:
            if "resultarr" not in obj:
                obj["resultarr"] = []
            obj["resultarr"].append({"address": obj["matchfilter"][j]["address"]})
    status = True
    for i in range(len(obj["hw_name"])):
        for j in range(len(obj["matchfilter"])):
            if ("instance_name" in obj["matchfilter"][j] or "registers.name" in obj["matchfilter"][j]) and status:
                db = mongo.db[settings.DB_Lookup[version][obj["hw_name"][i].upper()]]
                if "registers.name" in obj["matchfilter"][j]:
                    resultarr = list(db.aggregate(
                        [{"$match": obj["matchfilter"][j]}, {"$project": {"_id": 0}}, {"$unwind": "$registers"},
                         {"$match": obj["matchfilter"][j]}, {
                             "$project": {"base_address": 1, "instance_name": 1, "registers.address": 1,
                                          "registers.name": 1, "registers.absolute_address": 1}}]))
                    for x in resultarr:
                        if "resultarr" not in obj:
                            obj["resultarr"] = []
                        obj["resultarr"].append(
                            {"register_name": x["registers"]["name"], "instance_name": x["instance_name"],
                             "address": x["registers"]["absolute_address"]})
                    if len(resultarr):
                        status = False
                elif "instance_name" in obj["matchfilter"][j]:
                    resultarr = list(db.aggregate([{"$match": obj["matchfilter"][j]},
                                                   {"$project": {"_id": 0, "base_address": 1, "instance_name": 1}}]))
                    if "resultarr" not in obj:
                        obj["resultarr"] = []
                    for x in resultarr:
                        obj["resultarr"].append({"instance_name": x["instance_name"], "address": x["base_address"]})
                    if len(resultarr):
                        status = False
    if "resultarr" not in obj or len(obj["resultarr"]) <= 0:
        response["error"] = "Record not found"
        return response
    if "resultarr" in obj:
        for i in range(len(obj["resultarr"])):
            obj["resultarr"][i]["execute_command"] = ""
            if "command" in obj:
                obj["resultarr"][i]["execute_command"] += obj["command"]
            if "address" in obj["resultarr"][i]:
                obj["resultarr"][i]["execute_command"] += " " + obj["resultarr"][i]["address"]
            if "write_value" in obj:
                obj["resultarr"][i]["execute_command"] += " " + obj["write_value"]
            if "count" in obj:
                obj["resultarr"][i]["execute_command"] += " " + obj["count"]
            # obj["resultarr"][i]["execute_command"] +="\n"
            obj["resultarr"][i]["value"] = runcommandfromui(obj["resultarr"][i]["execute_command"].strip(),
                                                            "customdashboard", client)

        response["data"] = obj["resultarr"]
    return response

def findrefclock(obj,match,uniquekey):
    db = mongo.db.clock
    user = users.get_user(uniquekey, "connectionstatus","board", "host")
    for i in obj:
        if "value" in obj[i]:
            if not all(c in 'xX' + string.hexdigits for c in obj[i]["value"]):
            # if i=="APLL":
                obj[i]["value"] = "--"
                obj[i]["multiplier"] = "--"
                obj[i]["divider"] = "--"
                obj[i]["bypass"] = "--"
                obj[i]["selected_pll"] = "--"
                obj[i]["refclk"] = "--"
                continue
            obj[i]["value"] = bin(int(obj[i]["value"], 16))[2:]
            while len(obj[i]["value"]) < 32:
                obj[i]["value"] = '0' + obj[i]["value"]
            obj[i]["multiplier"] = int(findbitvalue(obj[i]["value"],fbdiv),2)
            obj[i]["divider"] = clkoutdivval[str(findbitvalue(obj[i]["value"],clkoutdiv))]
            obj[i]["bypass"] = findbitvalue(obj[i]["value"],bypassbit)
            obj[i]["selected_pll"] = i
            obj[i]["refclk"] = list(db.find({"clock":match,"uniqueid":uniquekey,"board":user["board"],"host":user["host"]},{"refclock":1}).sort("time"))
            if len(obj[i]["refclk"]) <= 0:
                obj[i]["refclk"] = refClock
            else:
                obj[i]["refclk"] = obj[i]["refclk"][len(obj[i]["refclk"])-1]["refclock"]
    return obj
def checkBinary(value):
    p = set(value)
    s = {'0', '1'}
    if s == p or p == {'0'} or p == {'1'}:
        return True
    else :
        return False

def findtargetfreq(responseObj,newObj,temp_xpd_obj,module_name):
    target_freq = round(float(responseObj["data"]["refclk"][newObj["Selected_PLL"].upper()]["refclk"]) * float(
    responseObj["data"]["refclk"][newObj["Selected_PLL"].upper()]["multiplier"]) / float(
    responseObj["data"]["refclk"][newObj["Selected_PLL"].upper()]["divider"]))
    if (module_name == "CRP" and newObj["Selected_PLL"] == "PPLL") or (module_name == "CRL" and newObj["Selected_PLL"] == "RPLL") or (module_name == "CRF" and newObj["Selected_PLL"] == "APLL") or (module_name == "CRP" and newObj["Selected_PLL"] == "NPLL"):
        return target_freq
    else:
        for i in temp_xpd_obj:
            if i == newObj["Selected_PLL"].upper():
                if "value" in temp_xpd_obj[i]:
                    if not checkBinary(temp_xpd_obj[i]["value"]):
                        temp_xpd_obj[i]["value"] = bin(int(temp_xpd_obj[i]["value"], 16))[2:]
                    while len(temp_xpd_obj[i]["value"]) < 32:
                        temp_xpd_obj[i]["value"] = '0' + temp_xpd_obj[i]["value"]
                    clkact = int(findbitvalue(temp_xpd_obj[i]["value"],25),2)
                    source_div = int(findbitvalue(temp_xpd_obj[i]["value"],"17:8"),2)
                    if clkact == 1:
                        #xpd_freq = target_freq/source_div
                        newObj["Absolute_Divider"] = newObj["Absolute_Divider"] * source_div
                        return target_freq
                    else:
                        return target_freq





def find_str(s, char):
    index = 0
    if char in s:
        c = char[0]
        for ch in s:
            if ch == c:
                if s[index:index+len(char)] == char:
                    return index
            index += 1
    return -1
def find_occurance(s, char):
    arr = []
    if char in s:
        c = char[0]
        index = 0
        for ch in s:
            if ch == c:
                if s[index:index + len(char)] == char:
                    arr.append(index)
            index += 1
    return arr

def create_phrase(char):
    arr = find_occurance(char, '*')
    if len(arr) > 1:  # multiple * only can occure for *name* valid syntax
        if len(arr) > 2:
            return -1
        else:
            if arr[0] == 0 and arr[1] == len(char)-1:  # if string is *name*
                char = re.compile(char[1:len(char) - 1],re.IGNORECASE)
    elif len(arr) ==1:
        if arr[0] == 0:
            char = char.replace("*", "") + "$"
            char = re.compile(char, re.IGNORECASE)
        elif arr[0] == len(char)-1:
            char = "^" + char.replace("*", "")
            char = re.compile(char, re.IGNORECASE)
        else:
            return -1
    else:
        if not all(c in 'xX' + string.hexdigits for c in char):
            char = re.compile(r"\b" + char + r"\b", re.IGNORECASE)
    return char
def refine_obj(str, char, obj):
    # index = find_str(str.lower(), char)
    index = str.lower().find(char)
    if index!=0:
        obj["error"] = "Invalid format"
        return obj
    str = (str[index + len(char):]).strip()
    str = str.split(" ")
    obj = buildQueryObj(str[0], obj)
    for i in range(1, len(str)):
        if ("0x" in str[i] or "0X" in str[i]):
            if all(c in 'xX' + string.hexdigits for c in str[i]):
                obj["write_value"] = str[i]
            else:
                obj["error"] = "Invalid format"
        elif str[i].isdigit():
            obj["count"] = str[i]
        else:
            obj["error"] = "Invalid format"
            try:
                obj["unknown"].append(str[i])
            except Exception as msg:
                # print(str(msg))
                obj["unknown"] = []
                obj["unknown"].append(str[i])
    return obj
def buildQueryObj(str,obj):
    str = str.split(' ')
    obj["filter"] = str[0]
    obj["filter"] = obj["filter"].split(',')
    for i in range(len(obj["filter"])):
        tempobj = {}
        temp = obj["filter"][i].split('.')
        if len(temp)>2:
            obj["error"] = "Invalid command"
            return obj
        for x in range(len(temp)):
            if x==0:
                if ("0x" in temp[x] or "0X" in temp[x]):
                    if all(c in 'xX' + string.hexdigits for c in temp[x]):
                        if len(temp)>1:
                            obj["error"]="Invalid command [address can't take . iteration]" #"." in address
                        else:
                            temp[x] = create_phrase(temp[x])
                            if temp[x] != -1:
                                tempobj["address"] = temp[x]
                            else:
                                obj["error"] = "Invalid format"
                                return obj
                    else:
                        obj["error"] = "Invalid format"
                        return obj
                else:
                    temp[x] = create_phrase(temp[x])
                    if temp[x] != -1:
                        tempobj["instance_name"]=temp[x]
                    else:
                        obj["error"] = "Invalid format"
                        return obj
            elif x==1:
                if ("0x" in temp[x] or "0X" in temp[x]):
                    if all(c in 'xX' + string.hexdigits for c in temp[x]):
                        obj["error"]="Invalid command [address can't take . iteration]" #"." in address
                    else:
                        obj["error"] = "Invalid command [address can't take . iteration]"  # "." in address
                else:
                    temp[x] = create_phrase(temp[x])
                    if temp[x] != -1:
                        tempobj["registers.name"]=temp[x]
        try:
            obj["matchfilter"].append(tempobj)
        except Exception as msg:
            obj["matchfilter"] = []
            obj["matchfilter"].append(tempobj)
            # print(str(msg))
    return obj

def findbitvalue(bitvalue, width):
    width = str(width).replace('[','').replace(']','')
    if ':' in width:
        width = width.split(':')
    else:
        width = width.split(',')
    if len(width) > 1:
        msb = int(width[0])
        lsb = int(width[1])
    else:
        msb = lsb = int(width[0])
    widthvalue= bitvalue[(len(bitvalue)-msb-1):(len(bitvalue)-lsb)]
    return widthvalue
def updatebitvalue(valuetomodify, value, bitposition):
    bitvalue = findbitvalue(value,bitposition)
    if len(valuetomodify)>bitposition:
        valuetomodify =valuetomodify[:31-bitposition]+bitvalue+valuetomodify[31-bitposition+1:]
    return valuetomodify

def addrow(i,row=0, column=0):
    if i["name"] != "me_core_module":
        i["row"] = row
        i["column"] = column
        i["maxrow"] = 7
        i["maxcolumn"] = 49
        i["is_me_npi"] = False
    else:
        if row == 0:
            i["row"] = 1
        else:
            i["row"] = row
        i["column"] = column
        i["maxrow"] = 8
        i["maxcolumn"] = 49
        i["is_me_npi"] = False
    if i["name"] == "me_npi":
        i["sort"] = 0
        i["is_me_npi"] = True
    else:
        i["sort"] = 1

def addRowColumn(hexVal, row, col):
    m_r = int(row) << 18
    m_c = int(col) << 23
    return hex(int(hexVal,16) + m_r + m_c)

def myconverter(o):
    if isinstance(o, datetime.datetime):
        return o.__str__()

@app.route('/getboardname/',methods=['GET'])
def getBoardName():
    try:
        response = {"status":"Fail","board_name":""}
        resetStatus = subprocess.Popen("sc_app -c board", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        resetResp,resetErr = resetStatus.communicate()
        if not resetErr:
            response["status"] = "Success"
            response["board_name"] = resetResp.decode().strip()
        return jsonify(response),200  
    except Exception as msg:
        return exception_handler(msg)

@app.route('/login/',methods=['POST'])
# @cross_origin(supports_credentials=True) # Send Access-Control-Allow-Headers
def login():
    try: 
        data = json.loads(request.data)
        username = data['username'] #request.args.get('username')
        password = data['password'] #request.args.get('password')
        if username == "Username" and password == "Password":
            uniqueid = username
            uname = 'Cockpit Admin'
            uid = username
        else:
            return jsonify({'error':'Internet connection is not available, please login as Cockpit Admin'}), 400
        resetStatus = subprocess.Popen("sc_app -c board", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        resetResp,resetErr = resetStatus.communicate()
        if resetErr is None:
            board_type = resetResp.decode().strip()
        else:
            board_type = ""
        #with open("designs.yml", "r") as rf:
            #pdi_lookup = yaml.safe_load(rf)
        #pdikey = board_type.lower()
        #if pdikey in pdi_lookup.keys():
            #pdi_list = pdi_lookup[pdikey]
        #else:
        pdi_list = {}
        userlist = users.get_userdetails(uniqueid)
        connectionstatus = 0
        if len(userlist) != 0 and "connectionstatus" in userlist[0]:
            connectionstatus = userlist[0]["connectionstatus"]
        if not connectionstatus:
            userobj = {"uniqueid":uniqueid,"username":uid,"full_name":uname,"status":"A","connectionstatus":0,"time":datetime.datetime.now()}
            if users.add_user(uniqueid,userobj):
                response = {'username':uid,"full_name":uname,"board_type": board_type,"pdi_list":pdi_list}
                return jsonify(response),200,{"uid":uniqueid, "Access-Control-Expose-Headers":"uid"}
            else:
                return jsonify({'error':'Internal Server Error'}), 500
        else:
            response = {'username':uid,"full_name":uname,"board_type": board_type,"pdi_list":pdi_list}
            return jsonify(response),200,{"uid":uniqueid, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/programversal/',methods=['POST'])
def programVersal():
    global socketdetails
    try:
        uniquekey = ""
        response = {"status":"Fail", "response":""}
        if len(socketdetails):
            for key in socketdetails:
                uniquekey = key
        else:
            uniquekey = "Username"
            userobj = {"uniqueid":"Username","username":"Username","full_name":"Cockpit Admin","status":"A","connectionstatus":0,"time":datetime.datetime.now()}
            if users.add_user(uniquekey,userobj):
                client = connecttoserver("localhost", 54321,uniquekey)
                client.get_gpio_switch()
                if (client):
                    time = datetime.datetime.timestamp(datetime.datetime.now())
                    users.set_user(uniquekey, {"connectionstatus": 1, "board": "localhost",
                                               "host": 54321, "boardpermission": client.boardpermission,
                                               "connetiontime": time,"server":request.url_root})
                    socketdetails[uniquekey] = client
        data = json.loads(request.data)
        trd = data["trd"]
        board_type = data["board_type"].lower()
        with open(os.path.join(os.path.dirname(os.path.abspath(__file__)),"designs.yml"), "r") as rf:
            pdi_lookup = yaml.safe_load(rf)
        pdi_list = pdi_lookup.get(data['board_type'].lower(), {})
        pdi_path = ""
        if pdi_list:
            if data["path"] == "":
                pdi_path = "/usr/bin/src/ACAP_Cockpit/designs/" + pdi_list[trd]
            else:
                pdi_path = data["path"]
            command = "device program "+ pdi_path
            response["response"] = runcommandfromui(command, "Programversal", socketdetails[uniquekey])
            if not response['response'][0]:
                response["status"] = "Success"
            else:
                response["status"] = "Fail"
                response["error"] = response['response']
        else:
            if data["trd"] == "manual":
                pdi_path = data["path"]
                command = "device program "+ pdi_path
                response["response"] = runcommandfromui(command, "Programversal", socketdetails[uniquekey])
                if not response['response'][0]:
                    response["status"] = "Success"
                else:
                    response["status"] = "Fail"
                    response["error"] = response['response']
            else:
                response["status"] = "Fail"
                response["error"] = "PDI not found"
        return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/resetversal/',methods=['GET'])
def resetVersal():
    try:
        response = {"status":"Fail"}
        resetStatus = subprocess.Popen("sc_app -c reset", shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        resetResp,resetErr = resetStatus.communicate()
        if not resetErr:
            response["status"] = "Success"
        return response
    except Exception as msg:
        return exception_handler(msg)

@app.route('/checkmodule', methods=['POST'])
def checkmodule():
    global socketdetails
    try:
        matchfilter = {}
        response = {"status": "Fail", "response": []}
        dataDict = json.loads(request.data)
        uniquekey = request.headers['uid']
        version = request.headers['version']
        users.set_user(uniquekey, {"checkmodule_request": True})
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if "hw_name" in dataDict and user["connectionstatus"]:
                response["status"] = "Success"
                hwname = dataDict["hw_name"]
                db = mongo.db[settings.DB_Lookup[version][hwname.upper()]]

            outputname = ""
            if "hw_name" in dataDict:
                outputname = outputname + dataDict["hw_name"]
                if "instance_name" in dataDict and type(dataDict["instance_name"]) != list:
                    outputname = outputname + "_" + dataDict["instance_name"]
                    matchfilter = {"instance_name":dataDict["instance_name"]}
                if "instance_name" in dataDict and type(dataDict["instance_name"]) == list:
                    matchfilter = {"instance_name":{"$in":dataDict["instance_name"]}}

            resultcursor = list(db.aggregate([{"$match":matchfilter},{"$project":{"_id":0,"instance_name":1,"base_address":1,"registers":1}},{"$unwind":"$registers"},{"$project":{"registers.address":1,"instance_name":1,"base_address":1,"registers.reset_value":1}}]))

            instance_data = {}
            for entry in resultcursor:
                instance_name = entry['instance_name']
                if instance_name not in instance_data:
                    instance_data[instance_name] = []
                instance_data[instance_name].append(entry)
            
            mods_list = [key for key in instance_data]
            modules_dict={}
            am012 = os.path.join(apidir,"AM012")
            for mod in mods_list:
                user = users.get_user(uniquekey, "clientconnectionstatus","checkmodule_request")
                if not (user['clientconnectionstatus'] and user["checkmodule_request"]):
                    return json.dumps({"status": "Inactive User Session, Process Terminated"}), 200, {"uid": uniquekey, "Access-Control-Expose-Headers": "uid"}
                tcl_file=f"{am012}/{mod}.tcl"
                data1 = rundicommands(f"source {tcl_file}","checkmodule_dbg", socketdetails[uniquekey],"", "", False)
                modules_dict[f'{mod}']=data1

                live_values_dict={}
                for key,value in modules_dict.items():
                    json_str = "".join(modules_dict[key])
                    key_value_pairs = json_str.split('}')
                    modules_dict2 = {}

                    for pair in key_value_pairs:
                        pair = pair.strip('{}')
                        parts = pair.split(':')
                        if len(parts) == 2:
                            address = parts[0].strip()
                            value = parts[1].strip()
                            if len(value) == 4:
                                value = f"0000{value}"
                            if address.startswith("{"):
                                address=address[1:]
                                if not address.startswith("0x"):
                                    address="0x"+address.lower()
                                    value="0x"+value.lower()
                                    modules_dict2[address] = value
                                else:
                                    modules_dict2[address] = value
                            else:
                                if not address.startswith("0x"):
                                    address="0x"+address.lower()
                                    value="0x"+value.lower()
                                    modules_dict2[address] = value
                                else:
                                    modules_dict2[address] = value
                    live_values_dict[key]=modules_dict2
            
            folderlocation = os.path.join(apidir,"modulecheck")
            if not os.path.exists(folderlocation):
                os.makedirs(folderlocation)
            filename = os.path.join(folderlocation, outputname+".json")
            fp = open(filename, "w")
            resultjson = []
            for i in range(len(resultcursor)):
                user = users.get_user(uniquekey, "clientconnectionstatus","checkmodule_request")
                if not (user['clientconnectionstatus'] and user["checkmodule_request"]):
                    return json.dumps({"status": "Inactive User Session, Process Terminated"}), 200, {"uid": uniquekey, "Access-Control-Expose-Headers": "uid"}
                absolute_address = hex(int(resultcursor[i]["base_address"], 16) + int(resultcursor[i]["registers"]["address"], 16))
                resultcursor[i]["absolute_address"]=absolute_address

                if all(c in 'xX' + string.hexdigits for c in absolute_address):
                    status = True
                    if status:
                        flag = True
                        for x in range(len(resultjson)):
                            if "instance_name" in resultjson[x] and resultjson[x]["instance_name"] == resultcursor[i]["instance_name"]:
                                if resultcursor[i]["absolute_address"] in live_values_dict[resultcursor[i]["instance_name"]]:
                                    live_value = live_values_dict[resultcursor[i]["instance_name"]][resultcursor[i]['absolute_address']]
                                else:
                                    live_value = "0x00000000"
                                if all(c in 'xX' + string.hexdigits for c in live_value):
                                    live_value = "0x"+str(live_value)
                                obj = {}
                                if str(resultcursor[i]["registers"]["reset_value"]).lower() == "" or str(resultcursor[i]["registers"]["reset_value"]).lower() == live_value:
                                    if resultjson[x]["match"]:
                                        resultjson[x]["match"] = True
                                        resultjson[x]["color"] = "#000000"
                                else:
                                    resultjson[x]["match"] = False
                                    resultjson[x]["color"] = "#ffcc99"
                                flag = False
                                break
                            else:
                                flag = True
                        if flag:
                            obj = {"instance_name":resultcursor[i]["instance_name"],"match":True,"color":"0xffffff"}
                            if resultcursor[i]["absolute_address"] in live_values_dict[resultcursor[i]["instance_name"]]:                                          
                                live_value = live_values_dict[resultcursor[i]["instance_name"]][resultcursor[i]['absolute_address']]
                            else:
                                live_value = "0x00000000"                                                                                                                                 
                            
                            if str(resultcursor[i]["registers"]["reset_value"]).lower() == "" or str(resultcursor[i]["registers"]["reset_value"]).lower() == live_value:
                                if obj["match"]:
                                    obj["match"] = True
                                    obj["color"] = "0x000000"
                            else:
                                obj["match"] = False
                                obj["color"] = "#ffcc99"
                            resultjson.append(obj)

            json.dump(resultjson, fp, indent=4)
            fp.close()
            with open(filename) as fp:
                data = json.load(fp)
                for i in data:
                    response["response"].append({"instance_name":i["instance_name"],"match":i["match"],"color":i["color"]})
            fp.close()                                                                                                      
            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/logout/',methods=['GET'])
def logout():
    try:
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            if users.del_user(uniquekey):
                return json.dumps("ok"), 200
            else:
                return jsonify({'error':'Internal Server Error'}), 500
        else:
            return jsonify({'error': 'Authentication Error'}), 400
    except Exception as msg:
        return exception_handler(msg)

@app.route('/files/<path:path>')
def get_file(path):
    try:
        temp = path.split('/')
        fileName = temp[len(temp) - 1]
        path = apidir
        for i in range(len(temp)):
            path = os.path.join(path, temp[i])
        if os.path.isfile(path):
            return send_file(path, download_name=fileName, as_attachment=True),200,{"Cache-Control": "no-cache"}
        else:
            return jsonify({"error":"File Not Found"})
    except Exception as msg:
        return exception_handler(msg)

@app.route('/logfiles/<uid>/<path:path>')
def get_log_file(uid,path):
    try:
        uid = request.headers['uid']
        fileName = path
        path = os.path.join(apidir,"log", uid, path)
        if os.path.isfile(path):
            return send_file(path, download_name=fileName, as_attachment=True),200,{"Cache-Control": "no-cache"}
        else:
            return jsonify({"error":"File Not Found"})
    except Exception as msg:
        return exception_handler(msg)

@app.route('/removelog')
def removelog():
    uid = request.headers['uid']
    return remove_older_folder(folder=uid,days=7)

@app.route('/getVersion')
def getVersion():
    return json.dumps(list(settings.DB_Lookup.keys()))

@app.route('/hardware/<path:path>', methods = ['post'])
def hwdetails(path):
    file = ""
    version = request.headers['version']
    db = mongo.db[settings.DB_Lookup[version][path.upper()]]
    file = path.upper()

    responcejson = []
    dataDict = json.loads(request.data)
    match_filter = {}
    if "instance_name" in dataDict:
        match_filter["instance_name"] = dataDict["instance_name"]
    if "hw_name" in dataDict:
        match_filter["hw_name"] = dataDict["hw_name"]
    if "instance_name" in dataDict:
        modules_cursor = db.find(match_filter, {'_id': 0, "registers": 1})
        for i in modules_cursor:
            for j in range(len(i["registers"])):
                if "register" in dataDict:
                    if dataDict["register"] == i["registers"][j]["name"]:
                        for k in range(len(i["registers"][j]["fields"])):
                            field = i["registers"][j]["fields"][k]["width"]
                            if isinstance(field, int):
                                field =field
                                i["registers"][j]["fields"][k]["sort"] = field
                            else:
                                field = (field.replace('[', '').replace(']','')).split(':')[0]
                                i["registers"][j]["fields"][k]["sort"] =int(field, 10)
                            responcejson.append(i["registers"][j]["fields"][k])
                        newlist = sorted(responcejson, key=lambda k: k['sort'], reverse=True)
                        responcejson = newlist
                else:
                    responcejson.append(i["registers"][j])
        for i in responcejson:
            if "address" in dataDict:
                i["address"] = hex(int(i["address"], 16) + int(dataDict["address"], 16))
                address = i["address"].split("0x")
                while len(address[1]) < 8 :
                    address[1] = "0" + address[1]
                i["address"] = "0x" + address[1]
                if "row" in dataDict and "column" in dataDict:
                    i["row"] = dataDict["row"]
                    i["column"] = dataDict["column"]
                    try:
                        i["address"] = addRowColumn(i["address"], dataDict["row"], dataDict["column"])
                    except Exception as msg:
                        # print(str(msg))
                        i["address"] = "0x00000000"
            i["live_value"] = ""
        if "live_value" in dataDict:
            folderpath = os.path.join(apidir, "modulecheck")
            filename = os.path.join(folderpath, file + ".json")
            my_file = Path(filename)
            if my_file.is_file():
                with open(filename) as fp:
                    data = json.load(fp)
                    for i in data:
                        if i["instance_name"] == dataDict["instance_name"]:
                            for j in responcejson:
                                for k in i["data"]:
                                    if j["name"] == k["registers_name"]:
                                        j["live_value"] = k["live_value"]
                                        j["match"] = k["match"]
                                        j["color"] = k["color"]
                fp.close()
        return json.dumps(responcejson)
    else:
        modules_cursor = db.find({}, {'_id': 0, "registers": 0})
        for i in modules_cursor:
            if path.upper() == "AI_ENGINE":
                addrow(i)
            if path == "ddr":
                if "DDR" in i["instance_name"]:
                    responcejson.append(i)
            elif path == "npi":
                if "DDR" not in i["instance_name"]:
                    responcejson.append(i)
            elif path == "pmc":
                if "PMC" in i["instance_name"]:
                    responcejson.append(i)
            elif path == "cpm":
                if "CPM" in i["instance_name"] or "PCIEA" in i["instance_name"] or "XDMA" in i["instance_name"]:
                    responcejson.append(i)
            elif path == "ps":
                if "PMC" not in i["instance_name"] and "CPM" not in i["instance_name"] and "PCIEA" not in i["instance_name"] and "XDMA" not in i["instance_name"]:
                    responcejson.append(i)
            else:
                responcejson.append(i)
            if path.upper() == "AI_ENGINE":
                newlist = sorted(responcejson, key=lambda k: k['sort'])
        for i in responcejson:
            if "row" in dataDict and "column" in dataDict:
                i["row"] = dataDict["row"]
                i["column"] = dataDict["column"]
                try:
                    i["base_address"] = addRowColumn(i["base_address"], dataDict["row"], dataDict["column"])
                except Exception as msg:
                    # print(str(msg))
                    i["base_address"] = "0x00000000"
        return json.dumps(responcejson)

@app.route('/getregvalue/', methods=['POST'])
def getregvalue():
    global socketdetails
    try:
        response = {"status":"Fail", "value":""}
        requestdata = request.get_json()
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if user["connectionstatus"]:
                response["status"] = "Success"
                response["value"] = getregistervalue(requestdata["address"],socketdetails[uniquekey])
            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/connect/', methods=['POST'])
def connect():
    global socketdetails
    try:
        response = {"status":"Fail"}
        requestdata = request.get_json()
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if not user["connectionstatus"]:
                db = mongo.db.usercollection
                activeclient = list(db.find(
                    {"board": requestdata["hostaddress"], "host": requestdata["port"], "boardpermission": "M",
                     "status": "A","connectionstatus":1}, {"_id": 0}))
                if len(activeclient):
                    if activeclient[0]["uniqueid"] in socketdetails and activeclient[0]["server"] == request.url_root:
                        socketdetails[uniquekey] = copy.copy(socketdetails[activeclient[0]["uniqueid"]])
                        client = socketdetails[uniquekey]
                        client.boardpermission = "S"
                        client.active_user = uniquekey
                    else:
                        response["status"] = 'Fail, Already connected to some board from different server'
                        return json.dumps(response), 200, {"uid": uniquekey, "Access-Control-Expose-Headers": "uid"}
                else:
                    client = connecttoserver(requestdata["hostaddress"], requestdata["port"],uniquekey)
                    client.get_gpio_switch()

                if (client):
                    time = datetime.datetime.timestamp(datetime.datetime.now())
                    users.set_user(uniquekey, {"connectionstatus": 1, "board": requestdata["hostaddress"],
                                               "host": requestdata["port"], "boardpermission": client.boardpermission,
                                               "connetiontime": time,"server":request.url_root})
                    socketdetails[uniquekey] = client
                    response["status"] = 'Success'
                    response["boardpermission"] = client.boardpermission
                    response["fread_status"] = getcommandresponse("config force-mem-accesses 1\n", "connect",socketdetails[uniquekey])
                    response["fread_status"] = getcommandresponse("config force-mem-accesses\n", "connect",socketdetails[uniquekey])
                    clockdb = mongo.db.clock
                    response["psrefclk"] = list(clockdb.find({"clock":"ps","uniqueid":uniquekey,"board":requestdata["hostaddress"],"host":requestdata["port"]},{"refclock":1}).sort("time"))
                    if len(response["psrefclk"]) <= 0:
                        response["psrefclk"] = refClock
                    else:
                        response["psrefclk"] = response["psrefclk"][len(response["psrefclk"])-1]["refclock"]
                    response["cpmrefclk"] = list(clockdb.find({"clock":"cpm","uniqueid":uniquekey,"board":requestdata["hostaddress"],"host":requestdata["port"]},{"refclock":1}).sort("time"))
                    if len(response["cpmrefclk"]) <= 0:
                        response["cpmrefclk"] = refClock
                    else:
                        response["cpmrefclk"] = response["cpmrefclk"][len(response["refclk"])-1]["refclock"]
                else:
                    response["status"] = "Fail"
            else:
                board = users.get_user(uniquekey, "board")  
                if board["board"] == requestdata["hostaddress"]:    
                    response["status"] = "Success"
                    response["boardpermission"] = users.get_user(uniquekey, "boardpermission")
                    response["fread_status"] = getcommandresponse("config force-mem-accesses 1\n", "connect",socketdetails[uniquekey])
                    response["fread_status"] = getcommandresponse("config force-mem-accesses\n", "connect",socketdetails[uniquekey])
                    clockdb = mongo.db.clock
                    response["psrefclk"] = list(clockdb.find({"clock":"ps","uniqueid":uniquekey,"board":requestdata["hostaddress"],"host":requestdata["port"]},{"refclock":1}).sort("time"))
                    if len(response["psrefclk"]) <= 0:
                        response["psrefclk"] = refClock
                    else:
                        response["psrefclk"] = response["psrefclk"][len(response["psrefclk"])-1]["refclock"]
                    response["cpmrefclk"] = list(clockdb.find({"clock":"cpm","uniqueid":uniquekey,"board":requestdata["hostaddress"],"host":requestdata["port"]},{"refclock":1}).sort("time"))
                    if len(response["cpmrefclk"]) <= 0:
                        response["cpmrefclk"] = refClock
                    else:
                        response["cpmrefclk"] = response["cpmrefclk"][len(response["refclk"])-1]["refclock"]

                else:
                    response["status"] = 'Fail, Already connected to some board'
            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/setmemaccess/')
def setmemaccess():
    global socketdetails
    try:
        response = {"status":"Fail"}
        dataDict = request.args.to_dict()
        uniquekey = request.headers['uid']
        if "enable" in dataDict:
            if users.required_login(uniquekey):
                user = users.get_user(uniquekey, "connectionstatus","board","host")
                if user["connectionstatus"]:
                    if dataDict["enable"] == "1":
                        data = getcommandresponse("config force-mem-accesses 1\n", "connect",socketdetails[uniquekey])
                        response["message"] = "Force memory read enabled successfully"
                    else:
                        data = getcommandresponse("config force-mem-accesses 0\n", "connect",socketdetails[uniquekey])
                        response["message"] = "Force memory read disabled successfully"
                    if(data.find("error") != -1):
                            response["status"] = "Fail"
                            response["message"] = data
                    else:
                        response["status"] = "Success"
                    return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)


@app.route('/disconnect')
def disconnect():
    global socketdetails,performancethread,configarr
    try:
        response = {"status":"Fail"}
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus","board","host")
            if user["connectionstatus"]:
                for i in range(len(threadarr) - 1, -1, -1):
                    if (hasattr(threadarr[i]["thread"], 'plotstatus')) and (uniquekey in threadarr[i]["threadname"]):
                        threadarr[i]["thread"].plotstatus = False
                    elif (hasattr(threadarr[i]["thread"], 'sysstatus')) and (uniquekey in threadarr[i]["threadname"]):
                        threadarr[i]["thread"].sysstatus = False
                    elif hasattr(threadarr[i]["thread"], 'serialcommstatus'):
                        threadarr[i]["thread"].serialcommstatus = False
                    elif hasattr(threadarr[i]["thread"], 'probstatus'):
                        threadarr[i]["thread"].probstatus = False
                    elif hasattr(threadarr[i]["thread"], 'sysiostatus'):
                        threadarr[i]["thread"].sysiostatus = False
                    elif uniquekey in threadarr[i]["threadname"]:
                        threadarr[i]["thread"].tabstatus = False
                    del threadarr[i]
                for i in range(len(performancethread) - 1, -1, -1):
                    if uniquekey in performancethread[i]["threadname"]:
                        performancethread[i]["thread"].tabstatus = False
                        for x in range(len(configarr) - 1, -1, -1):
                            if (configarr[x]["board"] == user["board"]) and (configarr[x]["port"] == user["host"]):
                                del configarr[x]
                    del performancethread[i]
                db = mongo.db.usercollection
                ysocket.runsyswatch = False
                activeclientlist = list(db.find(
                    {"board": socketdetails[uniquekey].host, "host": socketdetails[uniquekey].port, "status": "A",
                     "connectionstatus": 1}, {"_id": 0}).sort('connectiontime', pymongo.DESCENDING))
                if socketdetails[uniquekey].boardpermission == "M" and len(activeclientlist) > 1:
                    del socketdetails[uniquekey]
                    users.set_user(uniquekey, {"connectionstatus": 0, "boardpermission": ""})
                    for i in range(len(activeclientlist)):
                        if activeclientlist[i]["connectionstatus"] and activeclientlist[i]["boardpermission"] == "S":
                            users.set_user(activeclientlist[i]["uniqueid"], {"boardpermission": "M"})
                            socketdetails[activeclientlist[i]["uniqueid"]].boardpermission = "M"
                            response["status"] = 'Success'
                elif socketdetails[uniquekey].boardpermission == "S":
                    del socketdetails[uniquekey]
                    users.set_user(uniquekey, {"connectionstatus": 0, "boardpermission": ""})
                    response["status"] = 'Success'

                else:
                    try:
                        if(disconnectserver(socketdetails[uniquekey])):
                            users.set_user(uniquekey,{"connectionstatus":0})
                            if uniquekey in socketdetails:
                                del socketdetails[uniquekey]
                            response["status"] = 'Success'
                    except Exception as e:
                        print("error on disconnect------>>", str(e))
            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/getconnectionstatus')
def getconnectionstatus():
    try:
        response = {"status":"Fail"}
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus","board","host")
            if user["connectionstatus"]:
                response["status"] = "Success"
                response["hostname"] = user["board"]
                response["port"] = user["host"]
            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)


@app.route('/runcommand/', methods=['POST'])
def runcommand():
    global socketdetails
    try:
        requestdata = request.get_json()
        response = {"status":"Fail", "command":requestdata["command"], "response":""}
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if user["connectionstatus"]:
                response["status"] = "Success"
                command = requestdata["command"]
                cmdarr = command.split(" ")
                if (len(cmdarr) > 3) and (cmdarr[0] == "mrd") and len(cmdarr[3]) and (cmdarr[3]).isdigit():
                    response["response"] = runcmdloop(cmdarr[2], cmdarr[3], socketdetails[uniquekey])
                else:
                    response["response"] = runcommandfromui(command, "Debugger", socketdetails[uniquekey])
            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

def runcmdloop(address, size, uniquekey):
    global socketdetails
    dataarr = []
    if int(size) >= 0:
        dataarr = dataarr + (runcommandfromui(("mrd %s %s" % (address, str(size))), "Debugger",uniquekey))
    return dataarr


def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/runcommandfile/', methods=['GET', 'POST'])
def upload_file():
    global socketdetails
    try:
        response = {"status":"Fail", "response":""}
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if user["connectionstatus"] and (request.method == 'POST'):
                if 'file' not in request.files:
                    response["response"] = 'No file part'
                    return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
                file = request.files['file']

                if file.filename == '':
                    response["response"] = 'No selected file'
                    return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
                if file and allowed_file(file.filename):
                    filename = secure_filename(file.filename)
                    file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))

                    cmdFile = open(filename, "r")
                    if "xregv" in filename:
                        for line in cmdFile:
                            temparr = line.split("\t")
                            if len(temparr) >= 2:
                                getcommandresponse("mwr %s %s\n"%(temparr[0], temparr[1]), "Debugger",socketdetails[uniquekey])
                    else:
                        for line in cmdFile:
                            getcommandresponse(line, "File", socketdetails[uniquekey])
                    cmdFile.close()
                    response["status"] = "Success"
            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        print(str(msg))
        return jsonify({'error': 'Authentication Error'}), 400

@app.route('/refreshmodule/', methods=['POST'])
def refreshmodule():
    global socketdetails
    try:
        requestdata = request.get_json()
        addressarr = requestdata['address']
        responseArray = []
        response = {"status":"Fail", "response":responseArray}
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if user["connectionstatus"]:
                if len(addressarr):
                    for address in addressarr:
                        value = getregistervalue(address,socketdetails[uniquekey])
                        cmddic = {"address" : address, "value" : value}
                        if((not all(c in 'xX' + string.hexdigits for c in value)) or value.find("error") != -1):
                            cmddic["error"] = value
                        responseArray.append(cmddic)
                response["status"] = "Success"
                response["response"] = responseArray
            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/writetoregister/', methods=['POST'])
def writetoregister():
    global socketdetails
    try:
        requestdata = json.loads(request.data)
        responseArray = []
        response = {"status":"Fail", "response":responseArray}
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if user["connectionstatus"]:
                if len(requestdata):
                    for i in requestdata:
                        cmddic = {"address" : i["address"]}
                        message = getcommandresponse(("mwr %s %s\n"%(i["address"], i["value"])),"WriteToRegister",socketdetails[uniquekey])
                        if(message.find("error") != -1):
                            cmddic["error"] = message
                        responseArray.append(cmddic)
                response["status"] = "Success"
                response["response"] = responseArray
            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/gethwlist/')
def gethwlist():
    try:
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if user["connectionstatus"]:
                return jsonify({"status":"Success", "data":["PS","NPI", "DDR", "CPM", "AI Engine","PL"]}),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
            else:
                return jsonify({"status": "Fail", "data": []}),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/customdashboard/', methods=['POST'])
def customdashboard():
    global socketdetails
    try:
        response = {"status": "Fail", "data":[]}
        obj = {}
        uniquekey = request.headers['uid']
        version = request.headers['version']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if user["connectionstatus"]:
                response["status"] = "Success"
                if 'file' not in request.files:
                    dataDict = json.loads(request.data)
                    if "hw_name" not in dataDict and "command" not in dataDict:
                        response["error"] = "Invalid format"
                        return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
                    if "command" in dataDict and "hw_name" in dataDict:
                        obj["hw_name"] = dataDict["hw_name"]
                        response["command"] = dataDict["command"]
                        if "read".lower() in dataDict["command"].lower():
                            obj["command"]= "mrd"
                            obj = refine_obj(dataDict["command"],"read",obj)
                        elif "write".lower() in dataDict["command"].lower():
                            obj["command"] = "mwr"
                            obj = refine_obj(dataDict["command"], "write", obj)
                        else:
                            response["error"] = "Invalid format"
                            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
                    response = createcustomdashboardresponse(obj, response,socketdetails[uniquekey],version)
                else:
                    file = request.files['file']
                    if file.filename == '':
                        response["response"] = 'No selected file'
                        return json.dumps(response), 200, {"uid": uniquekey, "Access-Control-Expose-Headers": "uid"}
                    if file and allowed_file(file.filename):
                        filename = secure_filename(file.filename)
                        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))

                        userfile = open(filename, "r")
                        response["command"] = []
                        for i in userfile:
                            tempresponse = {"data":[]}
                            obj={}
                            obj["hw_name"] = ["PS","PMC","NPI","DDR","CPM"]
                            tempresponse["command"] = i.strip()
                            response["command"].append(tempresponse["command"])
                            if "read".lower() in tempresponse["command"].lower():
                                obj["command"] = "mrd"
                                obj = refine_obj(tempresponse["command"], "read", obj)
                            elif "write".lower() in tempresponse["command"].lower():
                                obj["command"] = "mwr"
                                obj = refine_obj(tempresponse["command"], "write", obj)
                            else:
                                tempresponse["error"] = "Invalid format"
                                # return json.dumps(tempresponse), 200, {"uid": uniquekey,
                                #                                    "Access-Control-Expose-Headers": "uid"}
                                response["data"].append({"command":tempresponse["command"],"error":tempresponse["error"]})
                            if "error" not in tempresponse:
                                var = createcustomdashboardresponse(obj, tempresponse,socketdetails[uniquekey],version)
                                for x in range(len(var["data"])):
                                    response["data"].append(json.loads(json.dumps(var["data"][x])))
                                for x in range(len(response["data"])):
                                    response["data"][x]["command"] = response["command"][x]
            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/getclockdetails/',methods=["POST"])
def getclockdetails():
    global socketdetails
    try:
        version = request.headers["version"]
        db = mongo.db[settings.DB_Lookup[version]["AM012"]]
        responseObj = {"status":"Fail", "data":{}}
        datadict = json.loads(request.data)
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus","board", "host")
            if user["connectionstatus"]:
                responseObj["status"] = "Success"
                if "refclk" in datadict:
                    clkdb = mongo.db.clock
                    clkdb.update_many({"clock":"ps","uniqueid":uniquekey,"board":user["board"],"host":user["host"]},{"$set": {"refclock":datadict["refclk"],"clock":"ps","time":datetime.datetime.now(),"uniqueid":uniquekey,"board":user["board"],"host":user["host"]}}, upsert=True)
                if "refresh" in datadict and datadict["refresh"]==False:
                    lastclock = mongo.db.clockdetails.find_one({"uniqueid":uniquekey,"board":user["board"],"host":user["host"],"clock":"ps"},{"_id":0,"clock":0,"time":0},sort=[('time', pymongo.DESCENDING)])
                    for i in lastclock["refclk"]:
                        lastclock["refclk"][i]["refclk"] = datadict["refclk"]
                    for i in lastclock["data"]:
                        for j in range(len(lastclock["data"][i])):
                            try:
                                lastclock["data"][i][j]["Target_Frequency"] = round(float(lastclock["refclk"][lastclock["data"][i][j]["Selected_PLL"].upper()]["refclk"]) * float(lastclock["refclk"][lastclock["data"][i][j]["Selected_PLL"].upper()]["multiplier"]) /float(lastclock["refclk"][lastclock["data"][i][j]["Selected_PLL"].upper()]["divider"]))
                                lastclock["data"][i][j]["Actual_Frequency"] = round(float(lastclock["data"][i][j]["Target_Frequency"])/float(lastclock["data"][i][j]["Absolute_Divider"]))
                            except Exception as msg:
                                print(str(msg))
                    responseObj["data"] = json.loads(json.dumps(lastclock))
                    tempvar = copy.deepcopy(lastclock)
                    tempvar["time"] = datetime.datetime.now()
                    tempvar["clock"] = "ps"
                    tempvar["board"] = user["board"]
                    tempvar["host"] = user["host"]
                    tempvar["uniqueid"] = uniquekey
                    clockdb = mongo.db.clockdetails
                    clockdb.update_many({"uniqueid":uniquekey,"board":user["board"],"host":user["host"],"clock":"ps"}, {"$set": tempvar}, upsert=True)
                    return json.dumps(responseObj),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
                apll = getcommandresponse(("mrd 0XFD1A0040\n"), "clock",socketdetails[uniquekey])
                rpll = getcommandresponse(("mrd 0xFF5E0040\n"), "clock",socketdetails[uniquekey])
                npll = getcommandresponse(("mrd 0xF1260050\n"), "clock",socketdetails[uniquekey])
                ppll=  getcommandresponse(("mrd 0xF1260040\n"), "clock",socketdetails[uniquekey])
                apll_xpd = getcommandresponse(("mrd 0xFD1A0100\n"), "clock", socketdetails[uniquekey])
                rpll_xpd = getcommandresponse(("mrd 0xFF5E0100\n"), "clock", socketdetails[uniquekey])
                npll_xpd = getcommandresponse(("mrd 0xF1260104\n"), "clock", socketdetails[uniquekey])
                ppll_xpd = getcommandresponse(("mrd 0xF1260100\n"), "clock", socketdetails[uniquekey])
                if not all(c in 'xX' + string.hexdigits for c in apll) or not all(c in 'xX' + string.hexdigits for c in rpll) or not all(c in 'xX' + string.hexdigits for c in npll) or not all(c in 'xX' + string.hexdigits for c in ppll) or not all(c in 'xX' + string.hexdigits for c in apll_xpd) or not all(c in 'xX' + string.hexdigits for c in rpll_xpd) or not all(c in 'xX' + string.hexdigits for c in npll_xpd) or not all(c in 'xX' + string.hexdigits for c in ppll_xpd):
                    responseObj["error"] = "Error while reading from board"
                    return json.dumps(responseObj),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
                tempobj = {"APLL":{"value":apll},"RPLL":{"value":rpll},"NPLL":{"value":npll},"PPLL":{"value":ppll}}
                tempobj = findrefclock(tempobj,"ps",uniquekey)
                temp_xpd_obj = {"APLL":{"value":apll_xpd},"RPLL":{"value":rpll_xpd},"NPLL":{"value":npll_xpd},"PPLL":{"value":ppll_xpd}}
                # temp_xpd_obj = find_spd_clock(tempobj,temp_xpd_obj)
                responseObj["data"]["refclk"] = tempobj
                responseObj["data"]["data"] = []

                finalarray = []

                innermatchfilter = {"registers.name":{"$regex":re.compile(r'.*_CTRL*.', re.IGNORECASE)}}
                clockcursor = list(db.aggregate([{"$match":{"instance_name":{"$in":["CRF", "CRL", "CRP"]}}},{"$project":{"_id":0, "instance_name":1,"base_address":1,"registers":1}},{"$unwind":"$registers"},{"$match":innermatchfilter},{"$project":{"registers.name":1,"registers.address":1,"instance_name":1,"base_address":1,"registers.fields":1}}]))
                for i in clockcursor:
                    selstatus = False
                    divstatus = False
                    for x in i["registers"]["fields"]:
                        if "SRCSEL" == x["name"].strip():
                            selstatus = True
                        if "CLKOUTDIV" == x["name"].strip() or "DIVISOR0" == x["name"].strip() or "DIVISOR" == x["name"].strip():
                            divstatus = True
                    if selstatus and divstatus:
                        finalarray.append(i)
                for i in range(len(finalarray)):
                    newObj= {}
                    parentbypass = True
                    newObj["Clock_Name"] = finalarray[i]["registers"]["name"]
                    obsolute_address = hex(int(finalarray[i]["base_address"], 16) + int(finalarray[i]["registers"]["address"], 16))
                    registervalue =getcommandresponse(("mrd %s\n"%obsolute_address), "clock",socketdetails[uniquekey])
                    newObj["Clock_Enable"] = "Enable"
                    if all(c in 'xX' + string.hexdigits for c in registervalue):
                        tempvar = bin(int(registervalue, 16))[2:]
                        while len(tempvar)<32:
                            tempvar ='0'+ tempvar
                        for j in range(len(finalarray[i]["registers"]["fields"])):
                            if "SRCSEL" == finalarray[i]["registers"]["fields"][j]["name"].strip().upper():
                                srcselwidth =finalarray[i]["registers"]["fields"][j]["width"]
                                try:
                                    temp = findbitvalue(tempvar, srcselwidth)
                                    newObj["Selected_PLL"] = srcselval[temp]
                                    if responseObj["data"]["refclk"][srcselval[temp]]["bypass"] == "0":
                                        parentbypass = True
                                    else:
                                        parentbypass = False
                                except Exception as msg:
                                    newObj["Selected_PLL"] = ""
                            if "CLKOUTDIV" == finalarray[i]["registers"]["fields"][j]["name"].strip().upper() or "DIVISOR0" == finalarray[i]["registers"]["fields"][j]["name"].strip().upper() or "DIVISOR" == finalarray[i]["registers"]["fields"][j]["name"].strip().upper():
                                clkdivwidth = finalarray[i]["registers"]["fields"][j]["width"]
                                newObj["Absolute_Divider"] = int(findbitvalue(tempvar, clkdivwidth), 2)
                            if "CLKACT" == finalarray[i]["registers"]["fields"][j]["name"].strip().upper():
                                actwidth = finalarray[i]["registers"]["fields"][j]["width"]
                                try:
                                    temp = findbitvalue(tempvar, actwidth)
                                    newObj["Clock_Enable"] = "Enable" if int(temp) == 1 else "Disable"
                                except Exception as msg:
                                    newObj["Clock_Enable"] = "Enable"
                        try:
                            newObj["Target_Frequency"] = findtargetfreq(responseObj,newObj,temp_xpd_obj,finalarray[i]["instance_name"])
                        except Exception as msg:
                            newObj["Target_Frequency"] = 0
                        try:
                            newObj["Actual_Frequency"] = round(float(newObj["Target_Frequency"])/float(newObj["Absolute_Divider"]))
                        except Exception as msg:
                            newObj["Actual_Frequency"] = newObj["Target_Frequency"]
                    else:
                        newObj["Selected_PLL"] = ""
                        newObj["Absolute_Divider"] = ""
                        newObj["Target_Frequency"] = ""
                        newObj["Actual_Frequency"] = ""
                        newObj["Clock_Enable"] = ""
                    if ((newObj["Selected_PLL"] != "" and newObj["Absolute_Divider"] != "") or (newObj["Selected_PLL"] == "" and newObj["Absolute_Divider"] == "")) and parentbypass:
                        responseObj["data"]["data"].append(newObj)
                get_item = operator.itemgetter('Selected_PLL')
                new_list = [list(g) for k, g in itertools.groupby(sorted(responseObj["data"]["data"], key=get_item), get_item)]

                resobj = {}
                for i in range(len(new_list)):
                    resobj[new_list[i][0]["Selected_PLL"]] = new_list[i]
                responseObj["data"]["data"] = resobj
                tempvar = copy.deepcopy(responseObj["data"])
                tempvar["time"] = datetime.datetime.now()
                tempvar["clock"] = "ps"
                tempvar["board"] = user["board"]
                tempvar["host"] = user["host"]
                tempvar["uniqueid"] = uniquekey
                clockdb = mongo.db.clockdetails
                clockdb.update_many({"uniqueid":uniquekey,"board":user["board"],"host":user["host"],"clock":"ps"}, {"$set":tempvar},upsert=True)
            return json.dumps(responseObj),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/getqosdata')
def getqosdata():
    try:
        response = {"status" : "Fail", "response" : ""}
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if user["connectionstatus"]:
                qoslist = []
                qosfile = open("%s"%header.QOS_LIST, "r")
                for line in qosfile:
                    qosdata = {}
                    line = line.replace("\n", "")
                    keys = line.split("\t")
                    if ((len(keys) >= 4) and (line[0] != '#')):
                        qosdata['address'] = keys[0]
                        qosdata['module_name'] = keys[1]
                        qosdata['register_name'] = keys[2]
                        qosdata['description'] = keys[4]
                        arr = keys[3].split(",")
                        widtharr = []
                        for element in arr:
                            tmp = element.split("-")
                            dic = {"width" : tmp[0], "name" : tmp[1]}
                            widtharr.append(dic)
                        qosdata['bitdetails'] = widtharr
                        qoslist.append(qosdata)
                response['status'] = "Success"
                response['response'] = qoslist
                qosfile.close()
            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/generatetclfile', methods=['POST'])
def generatetclfileforallmodule():
    matchfilter = {}
    dataDict = json.loads(request.data)
    version = request.headers['version']
    if "hw_name" in dataDict:
        hwname = dataDict["hw_name"]
        db = mongo.db[settings.DB_Lookup[version][hwname.upper()]]
        if hwname == "PL":
            db1 = mongo.db.plconfig

    outputname = ""
    if "hw_name" in dataDict:
        outputname = outputname + dataDict["hw_name"]
        if dataDict["hw_name"] == "DDR":
            matchfilter = {"instance_name":{"$in":[re.compile(r'DDR'), re.IGNORECASE]}}
        if dataDict["hw_name"] == "NPI":
            matchfilter = {"instance_name":{"$nin":[re.compile(r'DDR'), re.IGNORECASE]}}
        if dataDict["hw_name"] == "PMC":
            matchfilter = {"instance_name":{"$in":[re.compile(r'PMC'), re.IGNORECASE]}}
        if dataDict["hw_name"] == "CPM":
            matchfilter = {"instance_name":{"$in":[re.compile(r'CPM'),re.compile(r'XDMA'),re.compile(r'PCIEA'), re.IGNORECASE,]}}
        if dataDict["hw_name"] == "PS":
            matchfilter = {"instance_name":{"$nin":[re.compile(r'PMC'),re.compile(r'CPM'),re.compile(r'XDMA'),re.compile(r'PCIEA'), re.IGNORECASE,]}}
        if "instance_name" in dataDict:
            outputname = outputname + "_" + dataDict["instance_name"]

    if dataDict["hw_name"] == "PL":
        resultcursor = []
        if "board_name" in dataDict:
            config_cursor = db1.find({"board_name": dataDict["board_name"], "status": "A"})
            for j in config_cursor:
                for k in range(len(j["details"])):
                    if j["details"][k]["isChecked"]:
                        modules_cursor = db.aggregate([{"$match": {"name": j["details"][k]["name"]}}, {
                            "$project": {"_id": 0, "instance_name": 1, "base_address": 1, "registers": 1,"name":1}},
                                                          {"$unwind": "$registers"}, {
                                                              "$project": {"registers.name": 1, "registers.address": 1,
                                                                           "instance_name": 1, "base_address": 1,"name":1,
                                                                           "registers.fields": 1,
                                                                           "registers.reset_value": 1}}])
                        for i in modules_cursor:
                            if "instance_name" in j["details"][k] and i["name"] == j["details"][k]["name"]:
                                i["instance_name"] = j["details"][k]["instance_name"]
                            if "baseaddr" in j["details"][k] and i["name"] == j["details"][k]["name"]:
                                try:
                                    i["base_address"] = j["details"][k]["baseaddr"]
                                except Exception as msg:
                                    print(str(msg))
                                resultcursor.append(i)
    else:
        if "instance_name" in dataDict:
            matchfilter = {"instance_name":dataDict["instance_name"]}
        resultcursor = list(db.aggregate([{"$match":matchfilter},{"$project":{"_id":0,"instance_name":1,"base_address":1,"registers":1}},{"$unwind":"$registers"},{"$project":{"registers.name":1,"registers.address":1,"instance_name":1,"base_address":1,"registers.fields":1,"registers.reset_value":1}}]))
    if "format" in dataDict and dataDict["format"] == "zip":
        temparr = []
        get_item = operator.itemgetter('instance_name')
        new_list = [list(g) for k, g in itertools.groupby(sorted(resultcursor, key=get_item), get_item)]
        resobj = {}
        for i in range(len(new_list)):
            resobj[new_list[i][0]["instance_name"]] = new_list[i]
        for key, value in resobj.items():
            fp = open(key+".tcl", "w")
            temparr.append(key+".tcl")
            for i in range(len(value)):
                absolute_address = hex(
                    int(value[i]["base_address"], 16) + int(value[i]["registers"]["address"], 16))
                if dataDict["hw_name"].upper() == "AI_ENGINE" and "row" in dataDict and "column" in dataDict:
                    try:
                        absolute_address = addRowColumn(absolute_address, dataDict["row"], dataDict["column"])
                    except Exception as msg:
                        # print(str(msg))
                        absolute_address = "0x00000000"
                if all(c in 'xX' + string.hexdigits for c in absolute_address):
                    fp.write("# "+value[i]["instance_name"]+" >> "+value[i]["registers"]["name"]+" >> reset_value : "+str(value[i]["registers"]["reset_value"])+"\n")
                    for j in range(len(value[i]["registers"]["fields"])):
                        fp.write("# \t" + str(value[i]["registers"]["fields"][j]["name"]) + " >> " + str(value[i]["registers"]["fields"][j]["width"]) + "\n")
                    fp.write("mrd "+absolute_address+"\n")
            fp.close()
        z = zipfile.ZipFile(outputname+".zip", "w")
        for f in temparr:
            z.write(f)
        return send_file(os.path.join(apidir, outputname+".zip"), download_name=outputname+".zip", as_attachment=True),200,{"Cache-Control": "no-cache"}
    else:
        fp = open(outputname+".tcl", "w")
        for i in range(len(resultcursor)):
            absolute_address = hex(int(resultcursor[i]["base_address"], 16) + int(resultcursor[i]["registers"]["address"], 16))
            if dataDict["hw_name"].upper() == "AI_ENGINE" and "row" in dataDict and "column" in dataDict:
                try:
                    absolute_address = addRowColumn(absolute_address, dataDict["row"], dataDict["column"])
                except Exception as msg:
                    # print(str(msg))
                    absolute_address = "0x00000000"

            if all(c in 'xX' + string.hexdigits for c in absolute_address):
                status = True
                if dataDict["hw_name"] == "DDR":
                    if "DDR" in resultcursor[i]["instance_name"]:
                        status = True
                    else:
                        status = False
                if dataDict["hw_name"] == "NPI":
                    if "DDR" not in resultcursor[i]["instance_name"]:
                        status = True
                    else:
                        status = False
                if dataDict["hw_name"] == "PMC":
                    if "PMC" in resultcursor[i]["instance_name"]:
                        status = True
                    else:
                        status = False
                if dataDict["hw_name"] == "CPM":
                    if "CPM" in resultcursor[i]["instance_name"] or "PCIEA" in resultcursor[i]["instance_name"] or "XDMA" in resultcursor[i]["instance_name"]:
                        status = True
                    else:
                        status = False
                if dataDict["hw_name"] == "PS":
                    if "PMC" not in resultcursor[i]["instance_name"] and "CPM" not in resultcursor[i]["instance_name"] and "PCIEA" not in resultcursor[i]["instance_name"] and "XDMA" not in resultcursor[i]["instance_name"]:
                        status = True
                    else:
                        status = False
                if status:
                    fp.write("# "+resultcursor[i]["instance_name"]+" >> "+resultcursor[i]["registers"]["name"]+" >> reset_value : "+str(resultcursor[i]["registers"]["reset_value"])+"\n")
                    for j in range(len(resultcursor[i]["registers"]["fields"])):
                        fp.write("# \t" + str(resultcursor[i]["registers"]["fields"][j]["name"]) + " >> " + str(resultcursor[i]["registers"]["fields"][j]["width"]) + "\n")
                    fp.write("mrd "+absolute_address+"\n")
        fp.close()
        return send_file(os.path.join(apidir, outputname+".tcl"), download_name=outputname+".tcl", as_attachment=True),200,{"Cache-Control": "no-cache"}

@app.route('/phrasesearch', methods=['POST'])
def phrasesearch():
    response = []
    version = request.headers['version']
    dataDict = json.loads(request.data)
    if "hw_name" in dataDict:
        for x in range(len(dataDict["hw_name"])):
            matchfilter = {}
            registermatchfilter = {}
            fieldmatchfilter = {}
            hwname = dataDict["hw_name"][x]
            db = mongo.db[settings.DB_Lookup[version][hwname.upper()]]

            if hwname == "DDR":
                matchfilter = {"instance_name": {"$in": [re.compile(r'DDR'), re.IGNORECASE]}}
            if hwname == "NPI":
                matchfilter = {"instance_name": {"$nin": [re.compile(r'DDR'), re.IGNORECASE]}}
            if hwname == "PMC":
                matchfilter = {"instance_name": {"$in": [re.compile(r'PMC'), re.IGNORECASE]}}
            if hwname == "CPM":
                matchfilter = {"instance_name": {
                    "$in": [re.compile(r'CPM'), re.compile(r'XDMA'), re.compile(r'PCIEA'), re.IGNORECASE, ]}}
            if hwname == "PS":
                matchfilter = {"instance_name": {
                    "$nin": [re.compile(r'PMC'), re.compile(r'CPM'), re.compile(r'XDMA'), re.compile(r'PCIEA'),
                             re.IGNORECASE, ]}}
            if "instance_name" in dataDict and len(dataDict["instance_name"])>0:
                temparr = []
                if len(dataDict["instance_name"]) >=1 and dataDict["instance_name"][0] != "*":
                    for i in range(len(dataDict["instance_name"])):
                        char = create_phrase(dataDict["instance_name"][i])
                        if char == -1:
                           response["error"] = "Invalid keyword"
                        temparr.append(char)
                    if hwname == "DDR" or hwname == "NPI" or hwname == "PMC" or hwname == "CPM" or hwname == "PS":
                        newmatchfilter = {"$and":[{"instance_name":{"$in":temparr}},matchfilter]}
                        matchfilter = newmatchfilter
                    else:
                        matchfilter = {"instance_name":{"$in":temparr}}
            if "base_address" in dataDict and len(dataDict["base_address"])>0:
                temparr = []
                if len(dataDict["base_address"]) >=1 and dataDict["base_address"][0] != "*":
                    for i in range(len(dataDict["base_address"])):
                        if all(c in 'xX' + string.hexdigits for c in dataDict["base_address"][i]):
                            char = create_phrase(dataDict["base_address"][i])
                            if char == -1:
                                response["error"] = "Invalid keyword"
                            temparr.append(char)
                    matchaddrfilter = {"base_address":{"$in":temparr}}
            if "register_name" in dataDict and len(dataDict["register_name"])>0:
                temparr = []
                if len(dataDict["register_name"]) >=1 and dataDict["register_name"][0] != "*":
                    for i in range(len(dataDict["register_name"])):
                        char = create_phrase(dataDict["register_name"][i])
                        if char == -1:
                           response["error"] = "Invalid keyword"
                        temparr.append(char)
                    registermatchfilter = {"registers.name":{"$in":temparr}}
            if "register_address" in dataDict and len(dataDict["register_address"])>0:
                temparr = []
                if len(dataDict["register_address"]) >=1 and dataDict["register_address"][0] != "*":
                    for i in range(len(dataDict["register_address"])):
                        if all(c in 'xX' + string.hexdigits for c in dataDict["register_address"][i]):
                            char = create_phrase(dataDict["register_address"][i])
                            if char == -1:
                                response["error"] = "Invalid keyword"
                            temparr.append(char)
                    registeraddrmatchfilter = {"registers.absolute_address":{"$in":temparr}}
            if "fields_name" in dataDict and len(dataDict["fields_name"])>0:
                temparr = []
                if len(dataDict["fields_name"]) >=1 and dataDict["fields_name"][0] != "*":
                    for i in range(len(dataDict["fields_name"])):
                        char = create_phrase(dataDict["fields_name"][i])
                        if char == -1:
                           response["error"] = "Invalid keyword"
                        temparr.append(char)
                    fieldmatchfilter = {"registers.fields.name":{"$in":temparr}}

            if "fields_name" in dataDict and len(dataDict["fields_name"])>0:
                resultarr = list(db.aggregate([{"$match": matchfilter}, {"$project": {"_id": 0}},{"$unwind":"$registers"},{"$match":registermatchfilter},{"$project":{"_id":0}},{"$unwind":"$registers.fields"},{"$match":fieldmatchfilter},{"$project":{"_id":0}}]))
            elif "register_name" in dataDict and len(dataDict["register_name"])>0 and "register_address" in dataDict and len(dataDict["register_address"])>0:
                resultarr = list(db.aggregate([{"$match": matchfilter}, {"$project": {"_id": 0}}, {"$unwind": "$registers"},
                                               {"$match": {"$or":[registermatchfilter,registeraddrmatchfilter]}}, {"$project": {"_id": 0}}]))
            elif "register_name" in dataDict and len(dataDict["register_name"])>0:
                resultarr = list(
                    db.aggregate([{"$match": matchfilter}, {"$project": {"_id": 0}}, {"$unwind": "$registers"},
                                  {"$match": registermatchfilter},
                                  {"$project": {"_id": 0}}]))
            elif "register_address" in dataDict and len(dataDict["register_address"])>0:
                resultarr = list(
                    db.aggregate([{"$match": matchfilter}, {"$project": {"_id": 0}}, {"$unwind": "$registers"},
                                  {"$match": registeraddrmatchfilter},
                                  {"$project": {"_id": 0}}]))
            elif "instance_name" in dataDict and "base_address" in dataDict and len(dataDict["instance_name"])>0 and len(dataDict["base_address"])>0:
                resultarr = list(db.aggregate([{"$match":{"$or":[matchfilter,matchaddrfilter]}}, {"$project": {"_id": 0, "registers": 0}}]))
            elif "base_address" in dataDict and len(dataDict["base_address"])>0:
                resultarr = list(db.aggregate([{"$match": matchaddrfilter}, {"$project": {"_id": 0, "registers": 0}}]))
            else:
                resultarr = list(db.aggregate([{"$match": matchfilter}, {"$project": {"_id": 0,"registers":0}}]))

            if hwname.upper() == "AI_ENGINE":
                if "fields_name" in dataDict:
                    for i in range(len(resultarr)):
                        if "row" in dataDict and "column" in dataDict:
                            addrow(resultarr[i]["registers"]["fields"],dataDict["row"], dataDict["column"])
                        else:
                            addrow(resultarr[i]["registers"]["fields"])
                if "register_name" in dataDict:
                    for i in range(len(resultarr)):
                        if "row" in dataDict and "column" in dataDict:
                            addrow(resultarr[i]["registers"],dataDict["row"], dataDict["column"])
                        else:
                            addrow(resultarr[i]["registers"])
                else:
                    for i in range(len(resultarr)):
                        if "row" in dataDict and "column" in dataDict:
                            addrow(resultarr[i],dataDict["row"], dataDict["column"])
                        else:
                            addrow(resultarr[i])
            if "fields_name" in dataDict:
                for i in range(len(resultarr)):
                    resultarr[i]["registers"]["fields"]["key"] = hwname
            if "register_name" in dataDict:
                for i in range(len(resultarr)):
                    resultarr[i]["registers"]["key"] = hwname
            else:
                for i in range(len(resultarr)):
                    resultarr[i]["key"] = hwname
            for i in resultarr:
                response.append(i)

    return json.dumps(response)

@app.route('/getmeclockdetails/',methods=['POST'])
def getmeclockdetails():
    global socketdetails
    try:
        version = request.headers['version']
        db = mongo.db[settings.DB_Lookup[version]["AM012"]]
        responseObj = {"status": "Fail", "data": {}}
        datadict = json.loads(request.data)
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus","board","host")
            if user["connectionstatus"]:
                responseObj["status"] = "Success"
                if "refclk" in datadict:
                    clkdb = mongo.db.clock
                    clkdb.update_many({"clock": datadict["clock"],"uniqueid":uniquekey,"board":user["board"],"host":user["host"]},
                                 {"$set": {"refclock": datadict["refclk"], "clock": datadict["clock"], "time": datetime.datetime.now(),"uniqueid":uniquekey,"board":user["board"],"host":user["host"]}}, upsert=True)
                if "refresh" in datadict and datadict["refresh"] == False:
                    lastclock = mongo.db.clockdetails.find_one({"clock":datadict["clock"],"uniqueid":uniquekey,"board":user["board"],"host":user["host"]}, {"_id": 0, "clock": 0, "time": 0},
                                                               sort=[('time', pymongo.DESCENDING)])
                    for i in lastclock["refclk"]:
                        lastclock["refclk"][i]["refclk"] = datadict["refclk"]
                    for i in lastclock["data"]:
                        for j in range(len(lastclock["data"][i])):
                            try:
                                lastclock["data"][i][j]["Target_Frequency"] = round(
                                    float(lastclock["refclk"][lastclock["data"][i][j]["Selected_PLL"].upper()]["refclk"]) * float(
                                        lastclock["refclk"][lastclock["data"][i][j]["Selected_PLL"].upper()][
                                            "multiplier"]) / float(
                                        lastclock["refclk"][lastclock["data"][i][j]["Selected_PLL"].upper()]["divider"]))
                                lastclock["data"][i][j]["Actual_Frequency"] = round(float(lastclock["data"][i][j]["Target_Frequency"]) / float(lastclock["data"][i][j]["Absolute_Divider"]))
                            except Exception as msg:
                                print(str(msg))
                    responseObj["data"] = json.loads(json.dumps(lastclock))
                    tempvar = copy.deepcopy(lastclock)
                    tempvar["time"] = datetime.datetime.now()
                    tempvar["clock"] = datadict["clock"]
                    tempvar["board"] = user["board"]
                    tempvar["host"] = user["host"]
                    tempvar["uniqueid"] = uniquekey

                    clockdb = mongo.db.clockdetails
                    clockdb.update_many({"clock": datadict["clock"],"uniqueid":uniquekey,"board":user["board"],"host":user["host"]}, {"$set": tempvar}, upsert=True)
                    return json.dumps(responseObj),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
                refclk = getcommandresponse("mrd %s\n"%clock_ctrl[datadict["clock"]], "clock",socketdetails[uniquekey])
                if datadict["clock"] == "me":
                    npiclk = mongo.db.clockdetails.find_one({'clock': "ps"}, sort=[('time', pymongo.DESCENDING)])
                    npiclk = math.floor(npiclk["data"]["NPLL"][0]["Target_Frequency"])
# getting refclock till here
                if not all(c in 'xX' + string.hexdigits for c in refclk) :
                    responseObj["error"] = "Error while reading from board"
                    return json.dumps(responseObj),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}

                refclk = bin(int(refclk, 16))[2:]
                while len(refclk) < 32:
                    refclk = '0' + refclk
                tempobj = {clock_pll[datadict["clock"]]:{"value":refclk}}
                if datadict["clock"] == "me":
                    tempobj[clock_pll[datadict["clock"]]]["selected_pll"] = mepll[str(findbitvalue(refclk, '26:24'))[1:3]]
                elif datadict["clock"] == "cpm":
                    tempobj[clock_pll[datadict["clock"]]]["selected_pll"] = cpmpll[str(findbitvalue(refclk, '26:24'))[1:3]]
                tempobj[clock_pll[datadict["clock"]]]["divider"] = mediv[findbitvalue(refclk, '17:16')]
                tempobj[clock_pll[datadict["clock"]]]["multiplier"] = int(findbitvalue(refclk, '15:8'), 2)
                if tempobj[clock_pll[datadict["clock"]]]["selected_pll"] == "NPI_CLK":
                    tempobj[clock_pll[datadict["clock"]]]["refclk"] = npiclk
                else:
                    tempobj[clock_pll[datadict["clock"]]]["refclk"] = list(mongo.db.clock.find({"clock": datadict["clock"],"uniqueid":uniquekey,"board":user["board"],"host":user["host"]}, {"refclock": 1}).sort("time"))
                    if len(tempobj[clock_pll[datadict["clock"]]]["refclk"]) <= 0:
                        tempobj[clock_pll[datadict["clock"]]]["refclk"] = refClock
                    else:
                        tempobj[clock_pll[datadict["clock"]]]["refclk"] = tempobj[clock_pll[datadict["clock"]]]["refclk"][len(tempobj[clock_pll[datadict["clock"]]]["refclk"]) - 1]["refclock"]

                tempobj[clock_pll[datadict["clock"]]]["actual_frequency"] = round(float(tempobj[clock_pll[datadict["clock"]]]["refclk"])*float(tempobj[clock_pll[datadict["clock"]]]["multiplier"])/float(tempobj[clock_pll[datadict["clock"]]]["divider"]))
                responseObj["data"]["refclk"] = tempobj
                responseObj["data"]["data"] = []
                meclkarr = []
                # clk_freq = {}
                for i in clock_ref[datadict["clock"]]:
                    meclkarr.append({"clock_name":i, "value":getcommandresponse("mrd %s\n"%clock_ref[datadict["clock"]][i], "clock",socketdetails[uniquekey])})
                for i in range(len(meclkarr)):
                    newobj = {}
                    newobj["Clock_Name"] = meclkarr[i]["clock_name"]
                    tempvar = bin(int(meclkarr[i]["value"], 16))[2:]
                    while len(tempvar) < 32:
                        tempvar = '0' + tempvar
                    if newobj["Clock_Name"] != "CPM_TOPSW_REF_CTRL" :
                        newobj["Selected_PLL"] = clock_pll[datadict["clock"]]
                        newobj["Clock_Enable"] = "Enable" if int(findbitvalue(tempvar, 25),2) == 1 else "Disable"
                        newobj["Absolute_Divider"] = int(findbitvalue(tempvar, "17:8"),2)
                        newobj["Target_Frequency"] = tempobj[clock_pll[datadict["clock"]]]["actual_frequency"]
                        newobj["Actual_Frequency"] = round(
                            float(newobj["Target_Frequency"]) / float(newobj["Absolute_Divider"]))

                    else:
                        newobj["Selected_PLL"] = srcselval[findbitvalue(tempvar, "2:0")]
                        newobj["Clock_Enable"] = "Enable" if int(findbitvalue(tempvar, 25), 2) == 1 else "Disable"
                        newobj["Absolute_Divider"] = int(findbitvalue(tempvar, "17:8"), 2)
                        apll = getcommandresponse(("mrd 0XFD1A0040\n"), "clock", socketdetails[uniquekey])
                        rpll = getcommandresponse(("mrd 0xFF5E0040\n"), "clock", socketdetails[uniquekey])
                        npll = getcommandresponse(("mrd 0xF1260050\n"), "clock", socketdetails[uniquekey])
                        ppll = getcommandresponse(("mrd 0xF1260040\n"), "clock", socketdetails[uniquekey])
                        tempobj = {"APLL": {"value": apll}, "RPLL": {"value": rpll}, "NPLL": {"value": npll},
                                   "PPLL": {"value": ppll}}
                        tempobj = findrefclock(tempobj, "cpm", uniquekey)
                        try:
                            newobj["Target_Frequency"] = round(
                                float(tempobj[newobj["Selected_PLL"].upper()]["refclk"]) * float(
                                    tempobj[newobj["Selected_PLL"].upper()]["multiplier"]) / float(
                                    tempobj[newobj["Selected_PLL"].upper()]["divider"]))
                        except Exception as msg:
                            # print(str(msg))
                            newobj["Target_Frequency"] = 0
                        try:
                            newobj["Actual_Frequency"] = round(
                                float(newobj["Target_Frequency"]) / float(newobj["Absolute_Divider"]))
                        except Exception as msg:
                            # print(str(msg))
                            newobj["Actual_Frequency"] = newobj["Target_Frequency"]
                        newobj["Actual_Frequency"] = round(float(newobj["Target_Frequency"]) / float(newobj["Absolute_Divider"]))
                        responseObj["data"]["refclk"][newobj["Selected_PLL"].upper()] = tempobj[newobj["Selected_PLL"].upper()]
                    responseObj["data"]["data"].append(newobj)

                get_item = operator.itemgetter('Selected_PLL')
                new_list = [list(g) for k, g in itertools.groupby(sorted(responseObj["data"]["data"], key=get_item), get_item)]

                resobj = {}
                for i in range(len(new_list)):
                    resobj[new_list[i][0]["Selected_PLL"]] = new_list[i]
                responseObj["data"]["data"] = resobj
                if datadict["clock"] == "cpm":
                    responseObj["data"]["data"] = addpcieclock(responseObj["data"]["data"], uniquekey)
                tempvar = copy.deepcopy(responseObj["data"])
                tempvar["time"] = datetime.datetime.now()
                tempvar["clock"] = datadict["clock"]
                tempvar["board"] = user["board"]
                tempvar["host"] = user["host"]
                tempvar["uniqueid"] = uniquekey
                clockdb = mongo.db.clockdetails
                clockdb.update_many({"clock": datadict["clock"],"uniqueid":uniquekey,"board":user["board"],"host":user["host"]},{"$set": tempvar}, upsert=True)



            return json.dumps(responseObj),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)
def getbinvalue(hexaddress,uniquekey,n):
    global socketdetails
    tempvar = getcommandresponse("mrd %s\n"%hexaddress, "clock",socketdetails[uniquekey])
    tempvar = bin(int(tempvar, 16))[2:]
    while len(tempvar) < 32:
        tempvar = '0' + tempvar
    return tempvar[-n:]
def userfreq(binvalue, name, pcieclockname,uniquekey):
    if binvalue == "000":
        return "62.5/62.5"
    if binvalue == "001":
        return "125/125"
    if binvalue == "010":
        return "250/250"
    if binvalue == "011":
        coreclk = ""
        if "PCIe0" in name:
            coreclk = getbinvalue(pcieclockname["CRM_CORE_CLK_FREQ (CPM4_PCIE0_ATTR)"],uniquekey,5)
        if "PCIe1" in name:
            coreclk = getbinvalue(pcieclockname["CRM_CORE_CLK_FREQ (CPM4_PCIE1_ATTR)"],uniquekey,5)
        if coreclk == "0001":
            return "Reserved"
        elif coreclk == "00010":
            axiifwidth = getbinvalue("0xFCA50038",uniquekey,2)
            if axiifwidth == "11":
                return "250/500"
            else:
                return "Reserved"
        elif coreclk == "00100":
            axiifwidth = getbinvalue("0xFCA50038",uniquekey,2)
            if axiifwidth == "11":
                return "500/1000"
            else:
                return "Reserved"
        else:
            return "Reserved"
    if binvalue == "100":
        coreclk = ""
        if "PCIe0" in name:
            coreclk = getbinvalue(pcieclockname["CRM_CORE_CLK_FREQ (CPM4_PCIE0_ATTR)"],uniquekey,5)
        if "PCIe1" in name:
            coreclk = getbinvalue(pcieclockname["CRM_CORE_CLK_FREQ (CPM4_PCIE1_ATTR)"],uniquekey,5)
        if coreclk == "00010":
            axiifwidth = getbinvalue("0xFCA50038",uniquekey,2)
            if axiifwidth == "10":
                return "500/500"
            else:
                return "Reserved"
        else:
            return "Reserved"
    else:
        return "Reserved"
def addpcieclock(data,uniquekey):
    data["PCIe"] = []
    pcieclockname = {"CRM_CORE_CLK_FREQ (CPM4_PCIE0_ATTR)":"0xFCA50030","CRM_USER_CLK_FREQ (CPM4_PCIE0_ATTR)":"0xFCA50034","CRM_CORE_CLK_FREQ (CPM4_PCIE1_ATTR)":"0xFCA60030","CRM_USER_CLK_FREQ (CPM4_PCIE1_ATTR)":"0xFCA60034"}
    corefreq = {"001":"250","010":"500","100":"1000"}
    # userfreq = {"000":"62.5Mhz","001":"125Mhz","010":"250Mhz","011":getuserclock(pcieclockname,i)}
    for i in pcieclockname:
        if "Core" in i:
            data["PCIe"].append({"Clock_Name":i,"Selected_PLL":"","Clock_Enable":"","Absolute_Divider":"","Target_Frequency":"","Actual_Frequency":corefreq.get(getbinvalue(pcieclockname[i],uniquekey,3),"Reserved")})
        if "USER" in i:
            data["PCIe"].append({"Clock_Name":i,"Selected_PLL":"","Clock_Enable":"","Absolute_Divider":"","Target_Frequency":"","Actual_Frequency":userfreq(getbinvalue(pcieclockname[i],uniquekey,3),i,pcieclockname,uniquekey)})
    return data


@app.route('/configureplot/', methods=['POST'])
def configureplot():
    global threadarr,socketdetails,performancethread
    try:
        resultarr = []
        response = {"status": "Fail", "response": []}
        uniquekey = request.headers['uid']
        version = request.headers['version']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if user["connectionstatus"]:
                response["status"] = "Success"
                datadict = json.loads(request.data)
                for i in range(len(datadict)):
                    hw_name = module_name = address = register_name = bit_field = legend = displayname = y_axis = ""
                    matchfilter = registermatchfilter = fieldsmatchfilter = {}
                    dataDict = datadict[i]
                    if "hw_name" in dataDict and dataDict["hw_name"] != "":
                        hw_name = dataDict["hw_name"]
                        db = mongo.db[settings.DB_Lookup[version][hw_name.upper()]]
                        tempobj = {}
                        if "name" in dataDict and dataDict["name"] != "":
                            tempobj = buildQueryObj(dataDict["name"], tempobj)
                            if "error" in tempobj:
                                response["error"] = "Invalid format"
                                return json.dumps(response)
                            if "instance_name" in tempobj["matchfilter"][0]:
                                instance_name = tempobj["matchfilter"][0]["instance_name"]
                                if dataDict["hw_name"] == "DDR":
                                    matchfilter = {"$and": [
                                        {"instance_name": instance_name},
                                        {"instance_name": {"$in": [re.compile(r'DDR'), re.IGNORECASE]}}]}
                                elif dataDict["hw_name"] == "NPI":
                                    matchfilter = {"$and": [
                                        {"instance_name": instance_name},
                                        {"instance_name": {"$nin": [re.compile(r'DDR'), re.IGNORECASE]}}]}
                                elif dataDict["hw_name"] == "PMC":
                                    matchfilter = {"$and": [
                                        {"instance_name": instance_name},
                                        {"instance_name": {"$in": [re.compile(r'PMC'), re.IGNORECASE]}}]}
                                elif dataDict["hw_name"] == "CPM":
                                    matchfilter = {"$and": [
                                        {"instance_name": instance_name},
                                        {"instance_name": {
                                            "$in": [re.compile(r'CPM'), re.compile(r'XDMA'), re.compile(r'PCIEA'), re.IGNORECASE, ]}}]}
                                elif dataDict["hw_name"] == "PS":
                                    matchfilter = {"$and": [
                                        {"instance_name": instance_name},
                                        {"instance_name": {
                                            "$nin": [re.compile(r'PMC'), re.compile(r'CPM'), re.compile(r'XDMA'), re.compile(r'PCIEA'),
                                                     re.IGNORECASE, ]}}]}
                                else:
                                    matchfilter = {
                                        "instance_name": instance_name}
                            else:
                                response["error"] = "Invalid format"
                                return json.dumps(response)
                            if "registers.name" in tempobj["matchfilter"][0]:
                                registermatchfilter = {"registers.name": tempobj["matchfilter"][0]["registers.name"]}

                        if "address" in dataDict and dataDict["address"] != "":
                            address = dataDict["address"]
                        if "legend" in dataDict and dataDict["legend"] != "":
                            legend = dataDict["legend"]
                        if "displayname" in dataDict and dataDict["displayname"] != "":
                            displayname = dataDict["displayname"]
                        if "threadname" in dataDict and dataDict["threadname"] != "":
                            threadname = dataDict["threadname"]
                        if registermatchfilter != {} and matchfilter != {}:
                            resultarr = list(db.aggregate([
                                {"$match": matchfilter},
                                {"$project": {"_id": 0 }},
                                {"$unwind": "$registers"},
                                {"$match": registermatchfilter},
                                {"$group":{
                                    "_id":{"instance_name":"$instance_name","register_name":"$registers.name","address":"$registers.absolute_address"}}
                                },
                                {"$project": {"_id":0,"data":"$_id"}}
                                ]))
                        elif matchfilter != {}:
                            resultarr = list(db.aggregate(
                                [{"$match": matchfilter},
                                 {"$group": {
                                     "_id": {"instance_name": "$instance_name", "register_name": "$registers.name",
                                             "address": "$base_address"}}
                                 },
                                 {"$project": {"_id": 0, "data": "$_id"}}
                                 ]))
                        if len(resultarr)>0:
                            if "address" in resultarr[0]["data"]:
                                address = resultarr[0]["data"]["address"]
                            if "instance_name" in resultarr[0]["data"]:
                                module_name = resultarr[0]["data"]["instance_name"]
                            if "register_name" in resultarr[0]["data"]:
                                register_name = resultarr[0]["data"]["register_name"]
                            # if "field_name" in resultarr[0]["data"]:
                            #     field_name = resultarr[0]["data"]["field_name"]
                            if "hw_name" in resultarr[0]["data"]:
                                hw_name = resultarr[0]["data"]["hw_name"]
                            if "y_axis" in resultarr[0]["data"]:
                                hw_name = resultarr[0]["data"]["y_axis"]
                        if len(resultarr) > 0 or ("address" in dataDict and dataDict["address"] != ""):
                            newthread = plot.PikaClient(threadname,hw_name,module_name,register_name,bit_field,address,legend,displayname,y_axis,socketdetails[uniquekey],uniquekey)
                            threadarr.append({"threadname":newthread.threadname,"thread":newthread})
                            response["response"].append({"threadname":newthread.threadname,"thread_createtime":newthread.thread_createtime})
                            newthread.createthread()
                        else:
                            response["response"].append({"threadname": threadname,"error":"Record not found"})

            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/closeplot/', methods=['POST'])
def closeplot():
    global threadarr,performancethread,configarr
    try:
        response = {"status": "Fail", "response": []}
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus","board","host")
            # if user["connectionstatus"]:
            response["status"] = "Success"
            dataDict = json.loads(request.data)
            for l in range(len(dataDict)):
                if "threadname" in dataDict[l]:
                    for i in range(len(threadarr) -1,-1,-1):
                        if threadarr[i]["threadname"] == dataDict[l]["threadname"]:
                            if hasattr(threadarr[i]["thread"], 'plotstatus'):
                                threadarr[i]["thread"].plotstatus = False
                            elif hasattr(threadarr[i]["thread"], 'sysstatus'):
                                threadarr[i]["thread"].sysstatus = False
                            elif hasattr(threadarr[i]["thread"], 'serialcommstatus'):
                                threadarr[i]["thread"].serialcommstatus = False
                            elif hasattr(threadarr[i]["thread"], 'probstatus'):
                                threadarr[i]["thread"].probstatus = False
                            elif hasattr(threadarr[i]["thread"], 'sysiostatus'):
                                threadarr[i]["thread"].sysiostatus = False
                            else:
                                threadarr[i]["thread"].tabstatus = False
                            response["response"].append({threadarr[i]["threadname"]:"Success"})
                            del threadarr[i]
                    for i in range(len(performancethread) - 1, -1, -1):
                        if performancethread[i]["threadname"] == dataDict[l]["threadname"]:
                            performancethread[i]["thread"].tabstatus = False
                            response["response"].append({performancethread[i]["threadname"]: "Success"})
                            for x in range(len(configarr) - 1, -1, -1):
                                if ("threadname" in configarr[x]) and (configarr[x]["threadname"] == performancethread[i]["threadname"]) and (configarr[x]["board"] == user["board"]) and (configarr[x]["port"] == user["host"]):
                                    del configarr[x]
                            del performancethread[i]

            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/clockreset', methods=['POST'])
def clockreset():
    global socketdetails
    try:
        datadict = json.loads(request.data)
        response = {"status": "Fail", "response": []}
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if user["connectionstatus"]:
                response["status"] = "Success"
                fp = open(datadict["clock"]+"_clock_reset.tcl", 'r')
                count = 0
                headarr = []
                for line in fp:
                    if not line.startswith("#"):
                        line = line.split("\t")
                        if count == 0:
                            headarr = line
                        else:
                            newobj = {}
                            for j in range(len(line)):
                                newobj[headarr[j].strip()] = line[j].strip()
                            newobj["Live_Value"] = getcommandresponse(("mrd %s\n"%(newobj["Address"].strip())),"sysstatus",socketdetails[uniquekey])
                            if "error" not in newobj["Live_Value"] and "0x" not in newobj["Live_Value"]:
                                newobj["Live_Value"] = "0x"+newobj["Live_Value"]
                            if newobj["Live_Value"].lower() == newobj["Reset_Value"].lower():
                                newobj["Match"] = True
                            else:
                                newobj["Match"] = False
                            response["response"].append(newobj)
                        count =+1
                fp.close()
            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

@app.route('/watch', methods=['POST'])
def watch():
    global socketdetails
    global threadarr
    try:
        requestdata = request.get_json()
        response = {"status": "Fail", "response": []}
        uniquekey = request.headers['uid']
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if user["connectionstatus"]:
                cmdarr = []
                size = 0
                delay = 0.5
                threadname = ""
                response["status"] = "Success"
                if 'file' not in request.files:
                    if len(requestdata["command"])>0:
                        cmdarr = requestdata["command"]
                        size = requestdata["size"]
                        delay = requestdata["delay"]
                        threadname = requestdata["threadname"]
                else:
                    file = request.files['file']
                    if file.filename == '':
                        response["response"] = 'No selected file'
                        return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
                    if file and allowed_file(file.filename):
                        filename = secure_filename(file.filename)
                        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
                        threadname = uniquekey+"_watch"

                        cmdFile = open(filename, "r")
                        for line in cmdFile:
                            line = line.strip()
                            if line[0] != '#':
                                if(all(c in 'xX' + string.hexdigits for c in line)):
                                    cmdarr.append(line.replace("\n", ""))
                                else:
                                    return jsonify({'status':'Success','error': 'File format not supported'}), 200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
                        cmdFile.close()
                if len(cmdarr)>0:
                    newthread = syswatch.PikaClient(threadname,cmdarr,size,delay,True,socketdetails[uniquekey],uniquekey)
                    threadarr.append({"threadname": newthread.threadname, "thread": newthread})
                    response["response"].append({"threadname": newthread.threadname})
                    ysocket.runsyswatch = True
                    newthread.createthread()
                else:
                    response["response"].append({"threadname": threadname, "error": "Record not found"})
                    ysocket.runsyswatch = False
            return json.dumps(response),200,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
        else:
            return jsonify({'error': 'Authentication Error'}), 400,{"uid":uniquekey, "Access-Control-Expose-Headers":"uid"}
    except Exception as msg:
        return exception_handler(msg)

def check_last_bit(hexd):
    int_value = int(hexd,16)
    bin_value = bin(int_value)[2:]
    while len(bin_value) < 32:
        bin_value = '0' + bin_value
    if bin_value[-1] == '1' and bin_value[-2] == '0':
        return True
    else:
        return False

@app.route('/getregister/', methods=['POST'])
def getregister():
    global socketdetails
    try:
        uniquekey = ""
        if len(socketdetails):
            for key in socketdetails:
                uniquekey = key
        else:
            uniquekey = "Username"
            userobj = {"uniqueid":"Username","username":"Username","full_name":"Cockpit Admin","status":"A","connectionstatus":0,"time":datetime.datetime.now()}
            if users.add_user(uniquekey,userobj):
                client = connecttoserver("localhost", 54321,uniquekey)
                client.get_gpio_switch()
                if (client):
                    time = datetime.datetime.timestamp(datetime.datetime.now())
                    users.set_user(uniquekey, {"connectionstatus": 1, "board": "localhost",
                                               "host": 54321, "boardpermission": client.boardpermission,
                                               "connetiontime": time,"server":request.url_root})
                    socketdetails[uniquekey] = client
        addressarr = request.get_json()
        responseArray = []
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if user["connectionstatus"]:
                if len(addressarr):
                    for addressobj in addressarr:
                        value = getregistervalue(addressobj["address"],socketdetails[uniquekey], beam_target=addressobj["xsdbtarget"])
                        cmddic = {"address" : addressobj["address"], "value" : value,"status":"Success"}
                        if((not all(c in 'xX' + string.hexdigits for c in value)) or value.find("error") != -1):
                            cmddic["value"] = value
                            cmddic["status"] = "Fail"
                        else:
                            if "0x" not in cmddic["value"] or "0X" not in cmddic["value"]:
                                cmddic["value"] = "0x"+cmddic["value"]
                        responseArray.append(cmddic)
            else:
                if len(addressarr):
                    for addressobj in addressarr:
                        cmddic = {"address" : addressobj["address"], "value" : "Xsdbserver not connected","status":"Fail"}
                        responseArray.append(cmddic)
        return json.dumps(responseArray),200
    except Exception as msg:
        return exception_handler(msg)

@app.route('/setregister/', methods=['POST'])
def setregister():
    global socketdetails
    try:
        uniquekey = ""
        if len(socketdetails):
            for key in socketdetails:
                uniquekey = key
        requestdata = request.get_json()
        if users.required_login(uniquekey):
            user = users.get_user(uniquekey, "connectionstatus")
            if user["connectionstatus"]:
                responseArray = []
                for i in range(len(requestdata)):
                    if "address" in requestdata[i] and all(c in 'xX' + string.hexdigits for c in requestdata[i]["address"]):
                        if "xsdbtarget" in requestdata[i]:
                            latestvalue = getregistervalue(requestdata[i]["address"],socketdetails[uniquekey], beam_target=requestdata[i]["xsdbtarget"])
                        else:
                            latestvalue = getregistervalue(requestdata[i]["address"],socketdetails[uniquekey])
                        cmddic = {"address" : requestdata[i]["address"],"status":"Success"}
                        if latestvalue.find("Cannot read write-only register") != -1:
                            latestvalue = "0x00000000"
                        if((not all(c in 'xX' + string.hexdigits for c in latestvalue)) or latestvalue.find("error") != -1):
                            cmddic["status"] = "Fail"
                            cmddic["error"] = latestvalue
                            responseArray.append(cmddic)

                        else:
                            latestvalue = bin(int(latestvalue,16))[2:].zfill(32)
                            if "bitposition" in requestdata[i] and all(c in 'xX' + string.hexdigits for c in requestdata[i]["bitposition"]):
                                bitpositions = bin(int(requestdata[i]["bitposition"], 16))[2:].zfill(32)
                                bitpositions = find_occurance(bitpositions,"1")
                            if "bitstatus" in requestdata[i] and all(c in 'xX' + string.hexdigits for c in requestdata[i]["bitstatus"]):
                                bitstatus = bin(int(requestdata[i]["bitstatus"], 16))[2:].zfill(32)
                            for bpos in bitpositions:
                                latestvalue = updatebitvalue(latestvalue,bitstatus,31-bpos)
                            if "xsdbtarget" in requestdata[i]:
                                message = getcommandresponse(("mwr %s %s\n"%(requestdata[i]["address"], hex(int(latestvalue,2)))),"WriteToRegister",socketdetails[uniquekey],beam_target=requestdata[i]['xsdbtarget'])
                            else:
                                message = getcommandresponse(("mwr %s %s\n"%(requestdata[i]["address"], hex(int(latestvalue,2)))),"WriteToRegister")

                            if(message.find("error") != -1):
                                cmddic["error"] = message
                                cmddic["status"] = "Fail"
                            responseArray.append(cmddic)              
            else:
                if len(addressarr):
                    for address in addressarr:
                        cmddic = {"address" : address, "value" : "Xsdbserver not connected","status":"Fail"}
                        responseArray.append(cmddic)
        return json.dumps(responseArray),200
    except Exception as msg:
        return exception_handler(msg)

@app.after_request
def after_request(response):
    if request.method == "GET" or request.method == "POST":
        logger.error('%s %s %s %s %s', request.remote_addr, request.method, request.scheme, request.full_path, response.status)
        if any(api_path in request.full_path for api_path in ['disconnect', 'logout', 'connect']):
            logger.error("Request Body --->>%s", request.data.decode("utf-8"))
            logger.error("Response Body--->>%s", response.data.decode("utf-8"))
        try:
            logger.error('\tuser Id:--->>\t%s',response.headers['uid'])
        except:
            logger.error("\tUid is missing. Did user logged-in properly?")
        if "200" not in response.status:
            logger.error("Request Body --->>%s", request.data.decode("utf-8"))
            logger.error("Response Body--->>%s", response.data.decode("utf-8"))
    return response

@app.errorhandler(Exception)
def exceptions(e):
    tb = traceback.format_exc()
    logger.error('%s %s %s %s 5xx INTERNAL SERVER ERROR\n%s', request.remote_addr, request.method, request.scheme, request.full_path, tb)
    return e.status_code

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=49993,debug=False)

